Subversion Repositories shark

Rev

Rev 2 | 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
 ------------
21
 CVS :        $Id: pthread.c,v 1.1.1.1 2002-03-29 14:12:52 pj Exp $
22
 
23
 File:        $File$
24
 Revision:    $Revision: 1.1.1.1 $
25
 Last update: $Date: 2002-03-29 14:12:52 $
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;
138
  kern_cli();
139
  returnvalue = POSIX_getschedparam(level_sched, thread, policy,
140
                                    &param->sched_priority);
141
  kern_sti();
142
  return returnvalue;
143
}
144
 
145
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param)
146
{
147
  int returnvalue;
148
  kern_cli();
149
 
150
  returnvalue = POSIX_setschedparam(level_sched, thread, policy,
151
                                    param->sched_priority);
152
 
153
  if (!returnvalue)
154
    PC_set_task_ceiling(level_PC, thread,
155
                        sched_get_priority_max(SCHED_RR) -
156
                          param->sched_priority);
157
 
158
  kern_sti();
159
  return returnvalue;
160
}
161
 
162
 
163
/*---------------------------------------------------------------------*/
164
/* 13.6.2 Change the priority Ceiling of a Mutex                       */
165
/*---------------------------------------------------------------------*/
166
 
167
int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling,
168
                                 int *old_ceiling)
169
{
170
  int returnvalue = 0;
171
  int max = sched_get_priority_max(SCHED_RR);
172
 
173
  if (prioceiling > max || prioceiling < sched_get_priority_min(SCHED_RR))
174
    return EINVAL;
175
 
176
  mutex_lock(mutex);
177
  if (PC_set_mutex_ceiling(mutex,
178
                           max - prioceiling,
179
                           (DWORD *)old_ceiling))
180
    returnvalue = EINVAL;
181
 
182
  if (old_ceiling)
183
    *old_ceiling = max - *old_ceiling;
184
 
185
  mutex_unlock(mutex);
186
 
187
  return returnvalue;
188
}
189
 
190
int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex,
191
                                 int *prioceiling)
192
{
193
  PC_get_mutex_ceiling(mutex, (DWORD *)prioceiling);
194
  *prioceiling = sched_get_priority_max(SCHED_RR) - *prioceiling;
195
 
196
  return 0;
197
}
198
 
199
/*---------------------------------------------------------------------*/
200
/* 16.2.2 Thread Creation                                              */
201
/*---------------------------------------------------------------------*/
202
 
203
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
204
                   void *(*start_routine)(void *), void *arg)
205
{
206
  NRT_TASK_MODEL m;   // the scheduling model
207
  PC_RES_MODEL   pc;  // the resource model used for Priority Ceiling
208
  int olderrno;       // the pthread_create don't modify errno
209
 
210
  nrt_task_default_model(m);
211
  nrt_task_def_arg(m,arg);
212
  nrt_task_def_usemath(m);
213
  nrt_task_def_ctrl_jet(m);
214
  nrt_task_def_save_arrivals(m);
215
 
216
  if (attr) {
217
    nrt_task_def_stack(m,attr->stacksize);
218
    nrt_task_def_stackaddr(m,attr->stackaddr);
219
    if (attr->detachstate == PTHREAD_CREATE_JOINABLE)
220
      nrt_task_def_joinable(m);
221
    else
222
      nrt_task_def_unjoinable(m);
223
 
224
    nrt_task_def_weight(m, attr->schedparam.sched_priority);
225
    PC_res_default_model(pc, sched_get_priority_max(SCHED_RR) - attr->schedparam.sched_priority);
226
 
227
    nrt_task_def_policy(m,attr->schedpolicy);
228
    nrt_task_def_inherit(m,attr->inheritsched);
229
  }
230
  else {
231
    nrt_task_def_stack(m,PTHREAD_STACK_MIN);
232
    nrt_task_def_stackaddr(m,NULL);
233
    nrt_task_def_joinable(m);
234
 
235
    nrt_task_def_weight(m, sched_get_priority_min(SCHED_RR));
236
    PC_res_default_model(pc, sched_get_priority_max(SCHED_RR));
237
 
238
    nrt_task_def_policy(m,SCHED_RR);
239
    nrt_task_def_inherit(m,PTHREAD_EXPLICIT_SCHED);
240
  }
241
 
242
  olderrno = errno;
243
  *thread = task_createn("Posix task", start_routine,
244
                                       (TASK_MODEL *)&m,
245
                                       &pc, NULL);
246
  if (*thread != NIL)
247
    task_activate(*thread);
248
 
249
  errno = olderrno;
250
 
251
  if (*thread == NIL)
252
    return EINVAL;
253
  else
254
    return 0;
255
}
256
/*---------------------------------------------------------------------*/
257
/* 16.2.8 Dynamic Package initialization                               */
258
/*---------------------------------------------------------------------*/
259
 
260
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
261
{
262
  kern_cli();
263
  if (!(*once_control)) {
264
    *once_control = 1;
265
    kern_sti();
266
    init_routine();
267
  }
268
  else
269
    kern_sti();
270
  return 0;
271
}
272
 
273
 
274
 
275
/*---------------------------------------------------------------------*/
276
/* 18.2.1 Canceling Execution of a Thread                              */
277
/*---------------------------------------------------------------------*/
278
 
279
int pthread_cancel(pthread_t thread)
280
{
281
   int olderrno; // pthread_cancel doesn't modify errno
282
   int rvalue;   // the return value
283
 
284
   olderrno = errno;
285
   rvalue = task_kill(thread);
286
   errno = olderrno;
287
 
288
   if (rvalue)
289
     return (ESRCH);
290
   else
291
     return 0;
292
}
293
 
294
 
295