source: trunk/sys/libpthread/pthread_spinlock.c@ 202

Last change on this file since 202 was 1, checked in by alain, 9 years ago

First import

File size: 3.9 KB
Line 
1/*
2 * pthread_spinlock.c - pthread spinlock related functions
3 *
4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS.
8 *
9 * ALMOS is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <errno.h>
24#include <cpu-syscall.h>
25#include <pthread.h>
26
27#include <stdio.h>
28
29#undef dmsg_r
30#define dmsg_r(...)
31
32
33int pthread_spin_init (pthread_spinlock_t *lock, int pshared)
34{
35 if (lock == NULL)
36 return EINVAL;
37
38 lock->val = __PTHREAD_OBJECT_FREE;
39
40 return 0;
41}
42
43#include <unistd.h>
44
45int pthread_spin_lock (pthread_spinlock_t *lock)
46{
47 volatile uint_t cntr;
48 register bool_t isAtomic;
49 register uint_t this;
50 register uint_t limit;
51
52 if (lock == NULL)
53 {
54 dmsg_r(stderr, "%s: pid %d, tid %d, EINVAL\n",
55 __FUNCTION__, (int)getpid(), (unsigned)pthread_self);
56
57 return EINVAL;
58 }
59
60 this = (uint_t)pthread_self();
61
62 cpu_invalid_dcache_line(lock);
63
64 // Check if lock is not owned by the caller thread.
65 if (lock->val == this)
66 {
67 dmsg_r(stderr, "%s: pid %d, tid %d, 0x%x EDEADLK\n",
68 __FUNCTION__, (int)getpid(), (unsigned)pthread_self(), (unsigned)lock);
69
70 return EDEADLK;
71 }
72
73 cntr = 0;
74 limit = 10000;
75
76 // Take the lock
77 while((isAtomic = cpu_atomic_cas(&lock->val, __PTHREAD_OBJECT_FREE, (sint_t)this)) == false)
78 {
79 cntr ++;
80 if(cntr > limit)
81 {
82 pthread_yield();
83
84 dmsg_r(stderr, "%s: pid %d, tid %d, val %d, 0x%x, yielded\n",
85 __FUNCTION__, (int)getpid(), (unsigned)this, (unsigned)lock->val, (unsigned)lock);
86
87 cpu_invalid_dcache_line(lock);
88 limit = 2000;
89 cntr = 0;
90 }
91 }
92
93 dmsg_r(stderr, "%s: pid %d, tid %d, 0x%x locked\n",
94 __FUNCTION__, (int)getpid(), (unsigned)pthread_self(), (unsigned)lock);
95
96 return 0;
97}
98
99int pthread_spin_trylock(pthread_spinlock_t *lock)
100{
101 register bool_t isAtomic;
102 register uint_t this;
103
104 if(lock == NULL)
105 return EINVAL;
106
107 this = (uint_t)pthread_self();
108 cpu_invalid_dcache_line(lock);
109
110 // Check if lock is not owned by the caller thread.
111 if (lock->val == this)
112 return EDEADLK;
113
114 isAtomic = cpu_atomic_cas(&lock->val, __PTHREAD_OBJECT_FREE, (sint_t)this);
115
116 if(isAtomic == false)
117 {
118 cpu_invalid_dcache_line(lock);
119 return EBUSY;
120 }
121
122 return 0;
123}
124
125int pthread_spin_unlock (pthread_spinlock_t *lock)
126{
127 if (lock == NULL)
128 {
129 dmsg_r(stderr, "%s: pid %d, tid %d EINVAL\n",
130 __FUNCTION__, (int)getpid(), (unsigned)pthread_self());
131 return EINVAL;
132 }
133
134 // Check if lock is busy and owned by the caller thread.
135 if (lock->val != pthread_self())
136 {
137 dmsg_r(stderr, "libpthread: %s: pid %d, tid %d, val %d, EPERM\n",
138 __FUNCTION__, (int)getpid(), (int)pthread_self(), (int)lock->val);
139
140 return EPERM;
141 }
142 // Update lock's control informations
143 lock->val = __PTHREAD_OBJECT_FREE;
144 cpu_wbflush();
145 cpu_invalid_dcache_line(lock);
146
147 dmsg_r(stderr, "%s: pid %d, tid %d, 0x%x unlocked\n",
148 __FUNCTION__, (int)getpid(), (unsigned)pthread_self(), (unsigned)lock);
149
150 return 0;
151}
152
153int pthread_spin_destroy (pthread_spinlock_t *lock)
154{
155 if (lock == NULL)
156 return EINVAL;
157
158 // Check if lock is not occupied by a thread.
159 // If lock is occupied, then return immediately with EBUSY error code.
160 if(lock->val != __PTHREAD_OBJECT_FREE)
161 return EBUSY;
162
163 // Update lock's control informations.
164 lock->val = __PTHREAD_OBJECT_DESTROYED;
165 cpu_invalid_dcache_line(lock);
166 cpu_wbflush();
167 return 0;
168}
Note: See TracBrowser for help on using the repository browser.