1 /* $OpenBSD: rthread_spin_lock.c,v 1.5 2020/04/06 00:01:08 pirofti Exp $ */
2 /*
3 * Copyright (c) 2012 Paul Irofti <paul@irofti.net>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <errno.h>
19 #include <stdlib.h>
20
21 #include <pthread.h>
22
23 #include "rthread.h"
24
25 int
pthread_spin_init(pthread_spinlock_t * lock,int pshared)26 pthread_spin_init(pthread_spinlock_t *lock, int pshared)
27 {
28 pthread_spinlock_t l = NULL;
29
30 if (lock == NULL)
31 return (EINVAL);
32
33 if (pshared != PTHREAD_PROCESS_PRIVATE)
34 return (ENOTSUP);
35
36 l = calloc(1, sizeof *l);
37 if (l == NULL)
38 return (ENOMEM);
39
40 l->lock = _SPINLOCK_UNLOCKED;
41 *lock = l;
42 return (0);
43 }
44
45 int
pthread_spin_destroy(pthread_spinlock_t * lock)46 pthread_spin_destroy(pthread_spinlock_t *lock)
47 {
48 if (lock == NULL || *lock == NULL)
49 return (EINVAL);
50
51 if ((*lock)->owner != NULL)
52 return (EBUSY);
53
54 free(*lock);
55 *lock = NULL;
56 return (0);
57 }
58
59 int
pthread_spin_trylock(pthread_spinlock_t * lock)60 pthread_spin_trylock(pthread_spinlock_t *lock)
61 {
62 pthread_t self = pthread_self();
63 pthread_spinlock_t l;
64
65 if (lock == NULL || *lock == NULL)
66 return (EINVAL);
67
68 l = *lock;
69
70 if (l->owner == self)
71 return (EDEADLK);
72 if (!_spinlocktry(&l->lock))
73 return (EBUSY);
74
75 l->owner = self;
76 return (0);
77 }
78
79 int
pthread_spin_lock(pthread_spinlock_t * lock)80 pthread_spin_lock(pthread_spinlock_t *lock)
81 {
82 pthread_t self = pthread_self();
83 pthread_spinlock_t l;
84
85 if (lock == NULL || *lock == NULL)
86 return (EINVAL);
87
88 l = *lock;
89
90 if (l->owner == self)
91 return (EDEADLK);
92
93 _spinlock(&l->lock);
94 l->owner = self;
95 return (0);
96 }
97
98 int
pthread_spin_unlock(pthread_spinlock_t * lock)99 pthread_spin_unlock(pthread_spinlock_t *lock)
100 {
101 pthread_t self = pthread_self();
102 pthread_spinlock_t l;
103
104 if (lock == NULL || *lock == NULL)
105 return (EINVAL);
106
107 l = *lock;
108
109 if (l->owner != self)
110 return (EPERM);
111
112 l->owner = NULL;
113 _spinunlock(&l->lock);
114 return (0);
115 }
116