Subversion Repositories shark

Rev

Rev 271 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   (see the web pages for full authors list)
11
 *
12
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
13
 *
14
 * http://www.sssup.it
15
 * http://retis.sssup.it
16
 * http://shark.sssup.it
17
 */
18
 
19
/**
20
 ------------
318 giacomo 21
 CVS :        $Id: pthread.c,v 1.3 2003-11-05 15:05:12 giacomo Exp $
2 pj 22
 
23
 File:        $File$
318 giacomo 24
 Revision:    $Revision: 1.3 $
25
 Last update: $Date: 2003-11-05 15:05:12 $
2 pj 26
 ------------
27
 
28
 pthread.c
29
 
30
 This file contains the implementation of various posix primitives:
31
 
32
 refer to POSIX standard...
33
 
34
 maybe in the near future this functions will become inline functions...
35
 
36
**/
37
 
38
/*
39
 * Copyright (C) 2000 Paolo Gai
40
 *
41
 * This program is free software; you can redistribute it and/or modify
42
 * it under the terms of the GNU General Public License as published by
43
 * the Free Software Foundation; either version 2 of the License, or
44
 * (at your option) any later version.
45
 *
46
 * This program is distributed in the hope that it will be useful,
47
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
49
 * GNU General Public License for more details.
50
 *
51
 * You should have received a copy of the GNU General Public License
52
 * along with this program; if not, write to the Free Software
53
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
54
 *
55
 */
56
 
57
#include <kernel/const.h>
58
#include <kernel/func.h>
59
#include <pthread.h>
60
#include <errno.h>
61
#include <modules/pi.h>
62
#include <modules/pc.h>
63
#include <modules/posix.h>
64
 
65
// this fields are used to store the levels used in the pthread_functions...
66
static LEVEL level_sched;
67
static RLEVEL level_PI;
68
static RLEVEL level_PC;
69
 
70
// This function register the POSIX interface into the system...
71
void PTHREAD_register_module(LEVEL sched, RLEVEL pi, RLEVEL pc)
72
{
73
  level_sched = sched;
74
  level_PI    = pi;
75
  level_PC    = pc;
76
}
77
 
78
 
79
/*---------------------------------------------------------------------*/
80
/* 11.3.2 Initializing and Destroying a Mutex                          */
81
/*---------------------------------------------------------------------*/
82
 
83
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
84
{
85
  if (!attr || attr->protocol == PTHREAD_PRIO_NONE) {
86
    NOP_mutexattr_t m_nop;
87
 
88
    NOP_mutexattr_default(m_nop);
89
    return mutex_init(mutex,&m_nop);
90
  }
91
  else if (attr->protocol == PTHREAD_PRIO_INHERIT) {
92
    PI_mutexattr_t m_pi;
93
 
94
    PI_mutexattr_default(m_pi);
95
    return mutex_init(mutex,&m_pi);
96
  }
97
  else {   // PTHREAD_PRIO_PROTECT
98
    PC_mutexattr_t m_pc;
99
 
100
    PC_mutexattr_default(m_pc, sched_get_priority_max(SCHED_RR)-attr->prioceiling);
101
    return mutex_init(mutex,(mutexattr_t *)&m_pc);
102
  }
103
}
104
 
105
 
106
 
107
/*---------------------------------------------------------------------*/
108
/* 13.3.5 Yield processor                                              */
109
/*---------------------------------------------------------------------*/
110
 
111
int sched_yield(void)
112
{
113
  return POSIX_sched_yield(level_sched);
114
}
115
 
116
/*---------------------------------------------------------------------*/
117
/* 13.3.6 Get Scheduling Parameter Limits                              */
118
/*---------------------------------------------------------------------*/
119
 
120
int sched_get_priority_max(int policy)
121
{
122
  return POSIX_get_priority_max(level_sched);
123
}
124
 
125
int sched_rr_get_interval(pid_t pid, struct timespec *interval)
126
{
127
  return POSIX_rr_get_interval(level_sched);
128
}
129
 
130
/*---------------------------------------------------------------------*/
131
/* 13.5.2 Dynamic Thread Schedu ling Parameters Access                  */
132
/*---------------------------------------------------------------------*/
133
 
134
int pthread_getschedparam(pthread_t thread, int *policy,
135
                          struct sched_param *param)
136
{
137
  int returnvalue;
318 giacomo 138
  SYS_FLAGS f;
139
 
140
  f = kern_fsave();
2 pj 141
  returnvalue = POSIX_getschedparam(level_sched, thread, policy,
142
                                    &param->sched_priority);
318 giacomo 143
  kern_frestore(f);
2 pj 144
  return returnvalue;
145
}
146
 
147
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param)
148
{
149
  int returnvalue;
318 giacomo 150
  SYS_FLAGS f;
2 pj 151
 
318 giacomo 152
  f = kern_fsave();
153
 
2 pj 154
  returnvalue = POSIX_setschedparam(level_sched, thread, policy,
155
                                    param->sched_priority);
156
 
157
  if (!returnvalue)
158
    PC_set_task_ceiling(level_PC, thread,
159
                        sched_get_priority_max(SCHED_RR) -
160
                          param->sched_priority);
161
 
318 giacomo 162
  kern_frestore(f);
2 pj 163
  return returnvalue;
164
}
165
 
166
 
167
/*---------------------------------------------------------------------*/
168
/* 13.6.2 Change the priority Ceiling of a Mutex                       */
169
/*---------------------------------------------------------------------*/
170
 
171
int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling,
172
                                 int *old_ceiling)
173
{
174
  int returnvalue = 0;
175
  int max = sched_get_priority_max(SCHED_RR);
176
 
177
  if (prioceiling > max || prioceiling < sched_get_priority_min(SCHED_RR))
178
    return EINVAL;
179
 
180
  mutex_lock(mutex);
181
  if (PC_set_mutex_ceiling(mutex,
182
                           max - prioceiling,
183
                           (DWORD *)old_ceiling))
184
    returnvalue = EINVAL;
185
 
186
  if (old_ceiling)
187
    *old_ceiling = max - *old_ceiling;
188
 
189
  mutex_unlock(mutex);
190
 
191
  return returnvalue;
192
}
193
 
194
int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex,
195
                                 int *prioceiling)
196
{
197
  PC_get_mutex_ceiling(mutex, (DWORD *)prioceiling);
198
  *prioceiling = sched_get_priority_max(SCHED_RR) - *prioceiling;
199
 
200
  return 0;
201
}
202
 
203
/*---------------------------------------------------------------------*/
204
/* 16.2.2 Thread Creation                                              */
205
/*---------------------------------------------------------------------*/
206
 
207
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
208
                   void *(*start_routine)(void *), void *arg)
209
{
210
  NRT_TASK_MODEL m;   // the scheduling model
211
  PC_RES_MODEL   pc;  // the resource model used for Priority Ceiling
212
  int olderrno;       // the pthread_create don't modify errno
213
 
214
  nrt_task_default_model(m);
215
  nrt_task_def_arg(m,arg);
216
  nrt_task_def_usemath(m);
217
  nrt_task_def_ctrl_jet(m);
218
  nrt_task_def_save_arrivals(m);
271 giacomo 219
  nrt_task_def_level(m, level_sched);
2 pj 220
 
221
  if (attr) {
222
    nrt_task_def_stack(m,attr->stacksize);
223
    nrt_task_def_stackaddr(m,attr->stackaddr);
224
    if (attr->detachstate == PTHREAD_CREATE_JOINABLE)
225
      nrt_task_def_joinable(m);
226
    else
227
      nrt_task_def_unjoinable(m);
228
 
229
    nrt_task_def_weight(m, attr->schedparam.sched_priority);
230
    PC_res_default_model(pc, sched_get_priority_max(SCHED_RR) - attr->schedparam.sched_priority);
231
 
232
    nrt_task_def_policy(m,attr->schedpolicy);
233
    nrt_task_def_inherit(m,attr->inheritsched);
234
  }
235
  else {
236
    nrt_task_def_stack(m,PTHREAD_STACK_MIN);
237
    nrt_task_def_stackaddr(m,NULL);
238
    nrt_task_def_joinable(m);
239
 
240
    nrt_task_def_weight(m, sched_get_priority_min(SCHED_RR));
241
    PC_res_default_model(pc, sched_get_priority_max(SCHED_RR));
242
 
243
    nrt_task_def_policy(m,SCHED_RR);
244
    nrt_task_def_inherit(m,PTHREAD_EXPLICIT_SCHED);
245
  }
246
 
247
  olderrno = errno;
248
  *thread = task_createn("Posix task", start_routine,
249
                                       (TASK_MODEL *)&m,
250
                                       &pc, NULL);
251
  if (*thread != NIL)
252
    task_activate(*thread);
253
 
254
  errno = olderrno;
255
 
256
  if (*thread == NIL)
257
    return EINVAL;
258
  else
259
    return 0;
260
}
261
/*---------------------------------------------------------------------*/
262
/* 16.2.8 Dynamic Package initialization                               */
263
/*---------------------------------------------------------------------*/
264
 
265
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
266
{
318 giacomo 267
  SYS_FLAGS f;
268
 
269
  f = kern_fsave();
2 pj 270
  if (!(*once_control)) {
271
    *once_control = 1;
318 giacomo 272
    kern_frestore(f);
2 pj 273
    init_routine();
274
  }
275
  else
318 giacomo 276
    kern_frestore(f);
2 pj 277
  return 0;
278
}
279
 
280
 
281
 
282
/*---------------------------------------------------------------------*/
283
/* 18.2.1 Canceling Execution of a Thread                              */
284
/*---------------------------------------------------------------------*/
285
 
286
int pthread_cancel(pthread_t thread)
287
{
288
   int olderrno; // pthread_cancel doesn't modify errno
289
   int rvalue;   // the return value
290
 
291
   olderrno = errno;
292
   rvalue = task_kill(thread);
293
   errno = olderrno;
294
 
295
   if (rvalue)
296
     return (ESRCH);
297
   else
298
     return 0;
299
}
300
 
301
 
302