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 25int 26pthread_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 45int 46pthread_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 59int 60pthread_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 79int 80pthread_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 98int 99pthread_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