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

Last change on this file since 35 was 1, checked in by alain, 8 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.