source: trunk/sys/libpthread/pthread_condition.c@ 256

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

First import

File size: 4.6 KB
Line 
1/*
2 * pthread.c - conditions variables 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 <sys/types.h>
24#include <errno.h>
25#include <semaphore.h>
26#include <pthread.h>
27#include <sys/syscall.h>
28#include <cpu-syscall.h>
29
30typedef enum
31{
32 CV_INIT,
33 CV_WAIT,
34 CV_SIGNAL,
35 CV_BROADCAST,
36 CV_DESTROY
37} cv_operation_t;
38
39static int __sys_cond_var(void *sysid, int operation, sem_t *sem)
40{
41 register int retval;
42
43 retval = (int)cpu_syscall(sysid,(void*)operation,(void*)sem,NULL,SYS_COND_VAR);
44 return retval;
45}
46
47int pthread_condattr_init(pthread_condattr_t *attr)
48{
49 if(attr == NULL)
50 return EINVAL;
51
52 attr->scope = PTHREAD_PROCESS_PRIVATE;
53 return 0;
54}
55
56int pthread_condattr_destroy(pthread_condattr_t *attr)
57{
58 if(attr == NULL)
59 return EINVAL;
60
61 attr->scope = -1;
62 return 0;
63}
64
65int pthread_condattr_getpshared(pthread_condattr_t *attr, int *scope)
66{
67 if((attr == NULL) || (attr->scope < 0) || (scope == NULL))
68 return EINVAL;
69
70 *scope = attr->scope;
71 return 0;
72}
73
74int pthread_condattr_setpshared(pthread_condattr_t *attr, int scope)
75{
76 if((attr == NULL) || ((scope != PTHREAD_PROCESS_PRIVATE) && (scope != PTHREAD_PROCESS_SHARED)))
77 return EINVAL;
78
79 attr->scope = scope;
80 return 0;
81}
82
83int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
84{
85 int err;
86
87 if(cond == NULL) return EINVAL;
88
89 if((cond_attr != NULL) && (cond_attr->scope == PTHREAD_PROCESS_SHARED))
90 {
91 cond->scope = PTHREAD_PROCESS_SHARED;
92 return __sys_cond_var(&cond->sysid, CV_INIT, NULL);
93 }
94
95 cond->scope = PTHREAD_PROCESS_PRIVATE;
96
97 err = pthread_spin_init(&cond->lock, 0);
98
99 if(err) return err;
100
101 cond->count = 0;
102 return 0;
103}
104
105int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
106{
107 register __pthread_tls_t *tls;
108 register struct __shared_s *shared;
109 int err;
110
111 if((cond == NULL) || (mutex == NULL) || (mutex->attr.scope != cond->scope))
112 return EINVAL;
113
114 if(cond->scope == PTHREAD_PROCESS_SHARED)
115 return __sys_cond_var(&cond->sysid, CV_WAIT, &mutex->sem);
116
117 if(cond->count == 0)
118 list_root_init(&cond->queue);
119
120 cond->count ++;
121
122 tls = cpu_get_tls();
123 shared = (struct __shared_s*)__pthread_tls_get(tls, __PT_TLS_SHARED);
124
125 list_add_last(&cond->queue, &shared->list);
126
127 (void)pthread_mutex_unlock(mutex);
128
129 /* TODO: compute syscall return value (signals treatment) */
130 (void)cpu_syscall(NULL, NULL, NULL, NULL, SYS_SLEEP);
131
132 err = pthread_mutex_lock(mutex);
133 return err;
134}
135
136int pthread_cond_signal(pthread_cond_t *cond)
137{
138 struct __shared_s *next;
139 int err;
140
141 if(cond == NULL) return EINVAL;
142
143 if(cond->scope == PTHREAD_PROCESS_SHARED)
144 return __sys_cond_var(&cond->sysid, CV_SIGNAL, NULL);
145
146 if(cond->count == 0)
147 return 0;
148
149 next = list_first(&cond->queue, struct __shared_s, list);
150 list_unlink(&next->list);
151 cond->count --;
152
153 (void)cpu_syscall((void*)next->tid, NULL, NULL, NULL, SYS_WAKEUP);
154 return 0;
155}
156
157int pthread_cond_broadcast(pthread_cond_t *cond)
158{
159 struct list_entry root;
160 struct list_entry *list;
161 struct __shared_s *next;
162 uint_t count;
163 uint_t i;
164 int err = 0;
165
166 if(cond == NULL) return EINVAL;
167
168 if(cond->scope == PTHREAD_PROCESS_SHARED)
169 return __sys_cond_var(&cond->sysid, CV_BROADCAST, NULL);
170
171 if(cond->count == 0)
172 {
173 return 0;
174 }
175
176 count = cond->count;
177 cond->count = 0;
178 list_replace(&cond->queue, &root);
179
180 uint_t tbl[100];
181
182 i = 0;
183
184 while(count)
185 {
186 list_foreach_forward(&root, list)
187 {
188 next = list_element(list, struct __shared_s, list);
189 list_unlink(&next->list);
190 tbl[i] = next->tid;
191 count --;
192 i++;
193
194 if(i == 100)
195 {
196 i = 0;
197 (void)cpu_syscall((void*)tbl[0], (void*)&tbl[0], (void*)100, NULL, SYS_WAKEUP);
198 }
199 }
200 }
201
202 if(i != 0)
203 (void)cpu_syscall((void*)tbl[0], (void*)&tbl[0], (void*)i, NULL, SYS_WAKEUP);
204
205 return err;
206}
207
208int pthread_cond_destroy(pthread_cond_t *cond)
209{
210 int err = 0;
211
212 if(cond == NULL)
213 return EINVAL;
214
215 if(cond->scope == PTHREAD_PROCESS_SHARED)
216 return __sys_cond_var(&cond->sysid, CV_DESTROY, NULL);
217
218 if(cond->count != 0)
219 err = EBUSY;
220
221 return err;
222}
Note: See TracBrowser for help on using the repository browser.