[7f72217e] | 1 | /* |
---|
[eb5a7e07] | 2 | * $Id$ |
---|
[5e9b32b] | 3 | */ |
---|
| 4 | |
---|
| 5 | #include <pthread.h> |
---|
| 6 | #include <errno.h> |
---|
| 7 | |
---|
[f4719d5a] | 8 | #include <rtems/system.h> |
---|
[5e9b32b] | 9 | #include <rtems/score/object.h> |
---|
| 10 | #include <rtems/score/states.h> |
---|
| 11 | #include <rtems/score/watchdog.h> |
---|
| 12 | #include <rtems/posix/cond.h> |
---|
| 13 | #include <rtems/posix/time.h> |
---|
[af04a791] | 14 | #include <rtems/posix/mutex.h> |
---|
[5e9b32b] | 15 | |
---|
[974ff40] | 16 | /* |
---|
| 17 | * TEMPORARY |
---|
| 18 | */ |
---|
| 19 | |
---|
| 20 | void _POSIX_Condition_variables_MP_Send_process_packet ( |
---|
| 21 | POSIX_Condition_variables_MP_Remote_operations operation, |
---|
| 22 | Objects_Id condition_variables_id, |
---|
| 23 | Objects_Name name, |
---|
| 24 | Objects_Id proxy_id |
---|
| 25 | ) |
---|
| 26 | { |
---|
| 27 | (void) POSIX_MP_NOT_IMPLEMENTED(); |
---|
| 28 | } |
---|
| 29 | |
---|
| 30 | void _POSIX_Condition_variables_MP_Send_extract_proxy( |
---|
| 31 | Thread_Control *the_thread |
---|
| 32 | ) |
---|
| 33 | { |
---|
| 34 | (void) POSIX_MP_NOT_IMPLEMENTED(); |
---|
| 35 | } |
---|
| 36 | |
---|
| 37 | /* |
---|
| 38 | * END OF TEMPORARY |
---|
| 39 | */ |
---|
| 40 | |
---|
[5e9b32b] | 41 | /*PAGE |
---|
| 42 | * |
---|
| 43 | * The default condition variable attributes structure. |
---|
| 44 | */ |
---|
| 45 | |
---|
| 46 | const pthread_condattr_t _POSIX_Condition_variables_Default_attributes = { |
---|
| 47 | TRUE, /* is_initialized */ |
---|
| 48 | PTHREAD_PROCESS_PRIVATE /* process_shared */ |
---|
| 49 | }; |
---|
| 50 | |
---|
| 51 | /*PAGE |
---|
| 52 | * |
---|
| 53 | * _POSIX_Condition_variables_Manager_initialization |
---|
| 54 | * |
---|
| 55 | * This routine initializes all condition variable manager related data |
---|
| 56 | * structures. |
---|
| 57 | * |
---|
| 58 | * Input parameters: |
---|
| 59 | * maximum_condition_variables - maximum configured condition_variables |
---|
| 60 | * |
---|
| 61 | * Output parameters: NONE |
---|
| 62 | */ |
---|
| 63 | |
---|
| 64 | void _POSIX_Condition_variables_Manager_initialization( |
---|
| 65 | unsigned32 maximum_condition_variables |
---|
| 66 | ) |
---|
| 67 | { |
---|
| 68 | _Objects_Initialize_information( |
---|
| 69 | &_POSIX_Condition_variables_Information, |
---|
| 70 | OBJECTS_POSIX_CONDITION_VARIABLES, |
---|
| 71 | TRUE, |
---|
| 72 | maximum_condition_variables, |
---|
| 73 | sizeof( POSIX_Condition_variables_Control ), |
---|
| 74 | FALSE, |
---|
| 75 | 0, |
---|
| 76 | FALSE |
---|
| 77 | ); |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | /*PAGE |
---|
| 81 | * |
---|
| 82 | * 11.4.1 Condition Variable Initialization Attributes, |
---|
| 83 | * P1003.1c/Draft 10, p. 96 |
---|
| 84 | */ |
---|
| 85 | |
---|
| 86 | int pthread_condattr_init( |
---|
| 87 | pthread_condattr_t *attr |
---|
| 88 | ) |
---|
| 89 | { |
---|
| 90 | if ( !attr ) |
---|
| 91 | return EINVAL; |
---|
| 92 | |
---|
| 93 | *attr = _POSIX_Condition_variables_Default_attributes; |
---|
| 94 | return 0; |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | /*PAGE |
---|
| 98 | * |
---|
| 99 | * 11.4.1 Condition Variable Initialization Attributes, |
---|
| 100 | * P1003.1c/Draft 10, p. 96 |
---|
| 101 | */ |
---|
| 102 | |
---|
| 103 | int pthread_condattr_destroy( |
---|
| 104 | pthread_condattr_t *attr |
---|
| 105 | ) |
---|
| 106 | { |
---|
| 107 | if ( !attr || attr->is_initialized == FALSE ) |
---|
| 108 | return EINVAL; |
---|
| 109 | |
---|
| 110 | attr->is_initialized = FALSE; |
---|
| 111 | return 0; |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | /*PAGE |
---|
| 115 | * |
---|
| 116 | * 11.4.1 Condition Variable Initialization Attributes, |
---|
| 117 | * P1003.1c/Draft 10, p. 96 |
---|
| 118 | */ |
---|
| 119 | |
---|
| 120 | int pthread_condattr_getpshared( |
---|
| 121 | const pthread_condattr_t *attr, |
---|
| 122 | int *pshared |
---|
| 123 | ) |
---|
| 124 | { |
---|
| 125 | if ( !attr ) |
---|
| 126 | return EINVAL; |
---|
| 127 | |
---|
| 128 | *pshared = attr->process_shared; |
---|
| 129 | return 0; |
---|
| 130 | } |
---|
| 131 | |
---|
| 132 | /*PAGE |
---|
| 133 | * |
---|
| 134 | * 11.4.1 Condition Variable Initialization Attributes, |
---|
| 135 | * P1003.1c/Draft 10, p. 96 |
---|
| 136 | */ |
---|
| 137 | |
---|
| 138 | int pthread_condattr_setpshared( |
---|
| 139 | pthread_condattr_t *attr, |
---|
| 140 | int pshared |
---|
| 141 | ) |
---|
| 142 | { |
---|
| 143 | if ( !attr ) |
---|
| 144 | return EINVAL; |
---|
| 145 | |
---|
[c238a218] | 146 | switch ( pshared ) { |
---|
| 147 | case PTHREAD_PROCESS_SHARED: |
---|
| 148 | case PTHREAD_PROCESS_PRIVATE: |
---|
| 149 | attr->process_shared = pshared; |
---|
| 150 | return 0; |
---|
| 151 | |
---|
| 152 | default: |
---|
| 153 | return EINVAL; |
---|
| 154 | } |
---|
[5e9b32b] | 155 | } |
---|
| 156 | |
---|
| 157 | /*PAGE |
---|
| 158 | * |
---|
| 159 | * 11.4.2 Initializing and Destroying a Condition Variable, |
---|
| 160 | * P1003.1c/Draft 10, p. 87 |
---|
| 161 | */ |
---|
| 162 | |
---|
| 163 | int pthread_cond_init( |
---|
| 164 | pthread_cond_t *cond, |
---|
| 165 | const pthread_condattr_t *attr |
---|
| 166 | ) |
---|
| 167 | { |
---|
| 168 | POSIX_Condition_variables_Control *the_cond; |
---|
| 169 | const pthread_condattr_t *the_attr; |
---|
| 170 | |
---|
| 171 | if ( attr ) the_attr = attr; |
---|
| 172 | else the_attr = &_POSIX_Condition_variables_Default_attributes; |
---|
| 173 | |
---|
| 174 | /* |
---|
| 175 | * XXX: Be careful about attributes when global!!! |
---|
| 176 | */ |
---|
| 177 | |
---|
| 178 | if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED ) |
---|
| 179 | return POSIX_MP_NOT_IMPLEMENTED(); |
---|
| 180 | |
---|
| 181 | if ( !the_attr->is_initialized ) |
---|
| 182 | return EINVAL; |
---|
| 183 | |
---|
| 184 | _Thread_Disable_dispatch(); |
---|
| 185 | |
---|
| 186 | the_cond = _POSIX_Condition_variables_Allocate(); |
---|
| 187 | |
---|
| 188 | if ( !the_cond ) { |
---|
| 189 | _Thread_Enable_dispatch(); |
---|
| 190 | return ENOMEM; |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED && |
---|
| 194 | !( _Objects_MP_Allocate_and_open( &_POSIX_Condition_variables_Information, |
---|
| 195 | 0, the_cond->Object.id, FALSE ) ) ) { |
---|
| 196 | _POSIX_Condition_variables_Free( the_cond ); |
---|
| 197 | _Thread_Enable_dispatch(); |
---|
| 198 | return EAGAIN; |
---|
| 199 | } |
---|
| 200 | |
---|
| 201 | the_cond->process_shared = the_attr->process_shared; |
---|
| 202 | |
---|
[76f03c6] | 203 | the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX; |
---|
[5e9b32b] | 204 | |
---|
| 205 | /* XXX some more initialization might need to go here */ |
---|
| 206 | _Thread_queue_Initialize( |
---|
| 207 | &the_cond->Wait_queue, |
---|
| 208 | OBJECTS_POSIX_CONDITION_VARIABLES, |
---|
| 209 | THREAD_QUEUE_DISCIPLINE_FIFO, |
---|
| 210 | STATES_WAITING_FOR_CONDITION_VARIABLE, |
---|
| 211 | _POSIX_Condition_variables_MP_Send_extract_proxy, |
---|
| 212 | ETIMEDOUT |
---|
| 213 | ); |
---|
| 214 | |
---|
| 215 | _Objects_Open( |
---|
| 216 | &_POSIX_Condition_variables_Information, |
---|
| 217 | &the_cond->Object, |
---|
| 218 | 0 |
---|
| 219 | ); |
---|
| 220 | |
---|
| 221 | *cond = the_cond->Object.id; |
---|
| 222 | |
---|
| 223 | if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED ) |
---|
| 224 | _POSIX_Condition_variables_MP_Send_process_packet( |
---|
| 225 | POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_CREATE, |
---|
| 226 | the_cond->Object.id, |
---|
| 227 | 0, /* Name not used */ |
---|
| 228 | 0 /* Not used */ |
---|
| 229 | ); |
---|
| 230 | |
---|
| 231 | _Thread_Enable_dispatch(); |
---|
| 232 | |
---|
| 233 | return 0; |
---|
| 234 | } |
---|
| 235 | |
---|
| 236 | /*PAGE |
---|
| 237 | * |
---|
| 238 | * 11.4.2 Initializing and Destroying a Condition Variable, |
---|
| 239 | * P1003.1c/Draft 10, p. 87 |
---|
| 240 | */ |
---|
| 241 | |
---|
| 242 | int pthread_cond_destroy( |
---|
| 243 | pthread_cond_t *cond |
---|
| 244 | ) |
---|
| 245 | { |
---|
| 246 | register POSIX_Condition_variables_Control *the_cond; |
---|
| 247 | Objects_Locations location; |
---|
| 248 | |
---|
| 249 | the_cond = _POSIX_Condition_variables_Get( cond, &location ); |
---|
| 250 | switch ( location ) { |
---|
| 251 | case OBJECTS_ERROR: |
---|
| 252 | return EINVAL; |
---|
| 253 | case OBJECTS_REMOTE: |
---|
| 254 | _Thread_Dispatch(); |
---|
| 255 | return POSIX_MP_NOT_IMPLEMENTED(); |
---|
| 256 | return EINVAL; |
---|
| 257 | case OBJECTS_LOCAL: |
---|
| 258 | |
---|
[dce801d] | 259 | if ( _Thread_queue_First( &the_cond->Wait_queue ) ) { |
---|
| 260 | _Thread_Enable_dispatch(); |
---|
[95b76bc] | 261 | return EBUSY; |
---|
[dce801d] | 262 | } |
---|
[95b76bc] | 263 | |
---|
[5e9b32b] | 264 | _Objects_Close( |
---|
| 265 | &_POSIX_Condition_variables_Information, |
---|
| 266 | &the_cond->Object |
---|
| 267 | ); |
---|
| 268 | |
---|
| 269 | _POSIX_Condition_variables_Free( the_cond ); |
---|
| 270 | |
---|
| 271 | if ( the_cond->process_shared == PTHREAD_PROCESS_SHARED ) { |
---|
| 272 | |
---|
| 273 | _Objects_MP_Close( |
---|
| 274 | &_POSIX_Condition_variables_Information, |
---|
| 275 | the_cond->Object.id |
---|
| 276 | ); |
---|
| 277 | |
---|
| 278 | _POSIX_Condition_variables_MP_Send_process_packet( |
---|
| 279 | POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_DELETE, |
---|
| 280 | the_cond->Object.id, |
---|
| 281 | 0, /* Not used */ |
---|
| 282 | 0 /* Not used */ |
---|
| 283 | ); |
---|
| 284 | } |
---|
| 285 | _Thread_Enable_dispatch(); |
---|
| 286 | return 0; |
---|
| 287 | } |
---|
| 288 | return POSIX_BOTTOM_REACHED(); |
---|
| 289 | } |
---|
| 290 | |
---|
| 291 | /*PAGE |
---|
| 292 | * |
---|
| 293 | * _POSIX_Condition_variables_Signal_support |
---|
| 294 | * |
---|
| 295 | * A support routine which implements guts of the broadcast and single task |
---|
| 296 | * wake up version of the "signal" operation. |
---|
| 297 | */ |
---|
| 298 | |
---|
| 299 | int _POSIX_Condition_variables_Signal_support( |
---|
| 300 | pthread_cond_t *cond, |
---|
| 301 | boolean is_broadcast |
---|
| 302 | ) |
---|
| 303 | { |
---|
| 304 | register POSIX_Condition_variables_Control *the_cond; |
---|
| 305 | Objects_Locations location; |
---|
| 306 | Thread_Control *the_thread; |
---|
| 307 | |
---|
| 308 | the_cond = _POSIX_Condition_variables_Get( cond, &location ); |
---|
| 309 | switch ( location ) { |
---|
| 310 | case OBJECTS_ERROR: |
---|
| 311 | return EINVAL; |
---|
| 312 | case OBJECTS_REMOTE: |
---|
| 313 | _Thread_Dispatch(); |
---|
| 314 | return POSIX_MP_NOT_IMPLEMENTED(); |
---|
| 315 | return EINVAL; |
---|
| 316 | case OBJECTS_LOCAL: |
---|
| 317 | |
---|
| 318 | do { |
---|
| 319 | the_thread = _Thread_queue_Dequeue( &the_cond->Wait_queue ); |
---|
[cdcea6ce] | 320 | if ( !the_thread ) |
---|
[76f03c6] | 321 | the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX; |
---|
[5e9b32b] | 322 | } while ( is_broadcast && the_thread ); |
---|
[76f03c6] | 323 | |
---|
| 324 | _Thread_Enable_dispatch(); |
---|
| 325 | |
---|
[5e9b32b] | 326 | return 0; |
---|
| 327 | } |
---|
| 328 | return POSIX_BOTTOM_REACHED(); |
---|
| 329 | } |
---|
| 330 | |
---|
| 331 | /*PAGE |
---|
| 332 | * |
---|
| 333 | * 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 |
---|
| 334 | */ |
---|
| 335 | |
---|
| 336 | int pthread_cond_signal( |
---|
| 337 | pthread_cond_t *cond |
---|
| 338 | ) |
---|
| 339 | { |
---|
| 340 | return _POSIX_Condition_variables_Signal_support( cond, FALSE ); |
---|
| 341 | } |
---|
| 342 | |
---|
| 343 | /*PAGE |
---|
| 344 | * |
---|
| 345 | * 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 |
---|
| 346 | */ |
---|
| 347 | |
---|
| 348 | int pthread_cond_broadcast( |
---|
| 349 | pthread_cond_t *cond |
---|
| 350 | ) |
---|
| 351 | { |
---|
| 352 | return _POSIX_Condition_variables_Signal_support( cond, TRUE ); |
---|
| 353 | } |
---|
| 354 | |
---|
| 355 | /*PAGE |
---|
| 356 | * |
---|
| 357 | * _POSIX_Condition_variables_Wait_support |
---|
| 358 | * |
---|
| 359 | * A support routine which implements guts of the blocking, non-blocking, and |
---|
| 360 | * timed wait version of condition variable wait routines. |
---|
| 361 | */ |
---|
| 362 | |
---|
| 363 | int _POSIX_Condition_variables_Wait_support( |
---|
| 364 | pthread_cond_t *cond, |
---|
| 365 | pthread_mutex_t *mutex, |
---|
| 366 | Watchdog_Interval timeout |
---|
| 367 | ) |
---|
| 368 | { |
---|
| 369 | register POSIX_Condition_variables_Control *the_cond; |
---|
| 370 | Objects_Locations location; |
---|
| 371 | int status; |
---|
| 372 | |
---|
[5a234809] | 373 | if ( !_POSIX_Mutex_Get( mutex, &location ) ) { |
---|
| 374 | return EINVAL; |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | _Thread_Unnest_dispatch(); |
---|
| 378 | |
---|
[5e9b32b] | 379 | the_cond = _POSIX_Condition_variables_Get( cond, &location ); |
---|
| 380 | switch ( location ) { |
---|
| 381 | case OBJECTS_ERROR: |
---|
| 382 | return EINVAL; |
---|
| 383 | case OBJECTS_REMOTE: |
---|
| 384 | _Thread_Dispatch(); |
---|
| 385 | return POSIX_MP_NOT_IMPLEMENTED(); |
---|
| 386 | return EINVAL; |
---|
| 387 | case OBJECTS_LOCAL: |
---|
| 388 | |
---|
[76f03c6] | 389 | if ( the_cond->Mutex && ( the_cond->Mutex != *mutex ) ) { |
---|
| 390 | _Thread_Enable_dispatch(); |
---|
[cdcea6ce] | 391 | return EINVAL; |
---|
[76f03c6] | 392 | } |
---|
| 393 | |
---|
| 394 | the_cond->Mutex = *mutex; |
---|
[5e9b32b] | 395 | |
---|
| 396 | status = pthread_mutex_unlock( mutex ); |
---|
[5a234809] | 397 | /* XXX ignore this for now |
---|
[76f03c6] | 398 | if ( status ) { |
---|
| 399 | _Thread_Enable_dispatch(); |
---|
[48b40d8] | 400 | return EINVAL; |
---|
[76f03c6] | 401 | } |
---|
[5a234809] | 402 | */ |
---|
[5e9b32b] | 403 | |
---|
[cdcea6ce] | 404 | _Thread_queue_Enter_critical_section( &the_cond->Wait_queue ); |
---|
[76f03c6] | 405 | _Thread_Executing->Wait.return_code = 0; |
---|
| 406 | _Thread_Executing->Wait.queue = &the_cond->Wait_queue; |
---|
| 407 | _Thread_Executing->Wait.id = *cond; |
---|
[cdcea6ce] | 408 | |
---|
[76f03c6] | 409 | _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout ); |
---|
[5e9b32b] | 410 | |
---|
| 411 | _Thread_Enable_dispatch(); |
---|
| 412 | |
---|
[76f03c6] | 413 | /* |
---|
| 414 | * Switch ourself out because we blocked as a result of the |
---|
| 415 | * _Thread_queue_Enqueue. |
---|
| 416 | */ |
---|
| 417 | |
---|
| 418 | if ( _Thread_Executing->Wait.return_code ) |
---|
| 419 | return _Thread_Executing->Wait.return_code; |
---|
| 420 | |
---|
[5e9b32b] | 421 | status = pthread_mutex_lock( mutex ); |
---|
[af04a791] | 422 | if ( status ) |
---|
[48b40d8] | 423 | return EINVAL; |
---|
[5e9b32b] | 424 | |
---|
| 425 | return _Thread_Executing->Wait.return_code; |
---|
| 426 | } |
---|
| 427 | return POSIX_BOTTOM_REACHED(); |
---|
| 428 | } |
---|
| 429 | |
---|
| 430 | /*PAGE |
---|
| 431 | * |
---|
| 432 | * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105 |
---|
| 433 | */ |
---|
| 434 | |
---|
| 435 | int pthread_cond_wait( |
---|
| 436 | pthread_cond_t *cond, |
---|
| 437 | pthread_mutex_t *mutex |
---|
| 438 | ) |
---|
| 439 | { |
---|
| 440 | return _POSIX_Condition_variables_Wait_support( |
---|
| 441 | cond, |
---|
| 442 | mutex, |
---|
| 443 | THREAD_QUEUE_WAIT_FOREVER |
---|
| 444 | ); |
---|
| 445 | } |
---|
| 446 | |
---|
| 447 | /*PAGE |
---|
| 448 | * |
---|
| 449 | * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105 |
---|
| 450 | */ |
---|
| 451 | |
---|
| 452 | int pthread_cond_timedwait( |
---|
| 453 | pthread_cond_t *cond, |
---|
| 454 | pthread_mutex_t *mutex, |
---|
| 455 | const struct timespec *abstime |
---|
| 456 | ) |
---|
| 457 | { |
---|
[aae1c932] | 458 | if ( !abstime ) |
---|
| 459 | return EINVAL; |
---|
| 460 | |
---|
| 461 | /* XXX need to fully address an error occuring in the total timespec */ |
---|
| 462 | |
---|
| 463 | if ( abstime->tv_sec < 0 || abstime->tv_nsec < 0 ) |
---|
| 464 | return EINVAL; |
---|
| 465 | |
---|
| 466 | if ( abstime->tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) |
---|
| 467 | return EINVAL; |
---|
| 468 | |
---|
[5e9b32b] | 469 | return _POSIX_Condition_variables_Wait_support( |
---|
| 470 | cond, |
---|
| 471 | mutex, |
---|
[5b748a1] | 472 | _POSIX_Timespec_to_interval( abstime ) |
---|
[5e9b32b] | 473 | ); |
---|
| 474 | } |
---|