xref: /openbsd-src/lib/librthread/rthread_spin_lock.c (revision 8855e28c066fcedf8b2ce6df476d3f9b3d0ee8f9)
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