source: rtems/testsuites/psxtests/psxmsgq01/init.c @ 96bdacd

4.104.11
Last change on this file since 96bdacd was 96bdacd, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 9, 2009 at 2:49:27 PM

2009-11-09 Joel Sherrill <joel.sherrill@…>

  • psxmsgq01/init.c, psxsem01/init.c: Add service to check status returned by POSIX methods which return a pointer which is -1 on error. This eliminated some casts.
  • Property mode set to 100644
File size: 36.5 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2009.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 *
9 *  $Id$
10 */
11
12#define CONFIGURE_INIT
13#include "system.h"
14#include <sched.h>
15#include <fcntl.h>
16#include <time.h>
17#include <tmacros.h>
18#include <signal.h>   /* signal facilities */
19#include "test_support.h"
20
21typedef struct {
22  char         msg[ 50 ];
23  int          size;
24  unsigned int priority;
25}Test_Message_t;
26Test_Message_t Predefined_Msgs[MAXMSG+1];
27Test_Message_t Predefined_Msgs[MAXMSG+1] = {
28  { "12345678",   9, MQ_PRIO_MAX-1 },  /* Max Length Message med  */
29  { "",           1, 1             },  /* NULL  Message      low  */
30  { "Last",       5, MQ_PRIO_MAX   },  /* Queue Full Message hi   */
31  { "No Message", 0, MQ_PRIO_MAX-1 },  /* 0 length Message   med  */
32  { "1",          2, 0             },  /* Cause Overflow Behavior */
33};
34int Priority_Order[MAXMSG+1] = { 2, 0, 3, 1, MAXMSG };
35
36
37typedef struct {
38  mqd_t              mq;
39  Test_Queue_Types   index;
40  char              *name;
41  int                oflag;
42  int                maxmsg;
43  int                msgsize;
44  int                count;
45} Test_queue_type;
46
47Test_queue_type Test_q[ NUMBER_OF_TEST_QUEUES + 1 ] =
48{
49  { 0, 0, "Qread",    ( O_CREAT | O_RDONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
50  { 0, 1, "Qwrite",   ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
51  { 0, 2, "Qnoblock", ( O_CREAT | O_RDWR   | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
52  { 0, 3, "Qblock",   ( O_CREAT | O_RDWR )               , MAXMSG, MSGSIZE, 0 },
53  { 0, 4, "Qdefault", ( O_CREAT | O_RDWR )               , 10,     16,      0 },
54  { 0, 5, "mq6",      ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
55  { 0, 6, "Qblock",   (           O_RDWR )               , MAXMSG, MSGSIZE, 0 },
56};
57
58#define RW_NAME             Test_q[ RW_QUEUE ].name
59#define DEFAULT_NAME        Test_q[ DEFAULT_RW ].name
60#define RD_NAME             Test_q[ RD_QUEUE ].name
61#define WR_NAME             Test_q[ WR_QUEUE ].name
62#define BLOCKING_NAME       Test_q[ BLOCKING ].name
63#define CLOSED_NAME         Test_q[ CLOSED ].name
64
65#define RW_ATTR         Test_q[ RW_QUEUE ].oflag
66#define DEFAULT_ATTR    Test_q[ DEFAULT_RW ].oflag
67#define RD_ATTR         Test_q[ RD_QUEUE ].oflag
68#define WR_ATTR         Test_q[ WR_QUEUE ].oflag
69#define BLOCK_ATTR      Test_q[ BLOCKING ].oflag
70#define CLOSED_ATTR     Test_q[ CLOSED ].oflag
71
72/*
73 * Outputs a header at each test section.
74 */
75void Start_Test(
76  char *description
77)
78{
79  printf( "_______________%s\n", description );
80}
81
82
83void Validate_attributes(
84    mqd_t  mq,
85    int    oflag,
86    int    msg_count
87)
88{
89  int             status;
90  struct mq_attr  attr;
91
92  status = mq_getattr( mq, &attr );
93  fatal_posix_service_status( status, 0, "mq_getattr valid return status");
94
95  if ( mq != Test_q[ DEFAULT_RW ].mq ){
96    fatal_int_service_status((int)attr.mq_maxmsg, MAXMSG, "maxmsg attribute" );
97    fatal_int_service_status((int)attr.mq_msgsize,MSGSIZE,"msgsize attribute");
98  }
99
100  fatal_int_service_status((int)attr.mq_curmsgs, msg_count, "count attribute" );
101  fatal_int_service_status((int)attr.mq_flags, oflag, "flag attribute" );
102}
103
104#define Get_Queue_Name( i )  Test_q[i].name
105char *Build_Queue_Name( int i ) {
106
107  static char Queue_Name[PATH_MAX + 2]; 
108
109  sprintf(Queue_Name,"mq%d", i+1 );
110  return Queue_Name;
111}
112
113void open_test_queues(void)
114{
115  struct mq_attr   attr;
116  int              status;
117  Test_queue_type *tq;
118  int              que;
119
120  attr.mq_maxmsg  = MAXMSG;
121  attr.mq_msgsize = MSGSIZE;
122
123  puts( "Init: Open Test Queues" );
124
125  for( que = 0; que < NUMBER_OF_TEST_QUEUES+1; que++ ) {
126
127    tq = &Test_q[ que ];
128    if ( que == DEFAULT_RW)
129      Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, NULL );
130    else
131      Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, &attr );
132
133    assert( Test_q[que].mq != (-1) );
134  }
135
136  status = mq_close( Test_q[NUMBER_OF_TEST_QUEUES].mq );
137  fatal_posix_service_status( status, 0, "mq_close duplicate message queue");
138  status = mq_close( Test_q[CLOSED].mq );
139  fatal_posix_service_status( status, 0, "mq_close message queue");
140  status = mq_unlink( CLOSED_NAME );
141  fatal_posix_service_status( status, 0, "mq_unlink message queue");
142}
143
144/*
145 * Opens CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES then leaves size queues
146 * opened but closes the rest.
147 */
148
149void validate_mq_open_error_codes(void)
150{
151  int             i;
152  mqd_t           n_mq2;
153  struct mq_attr  attr;
154  int             status;
155  mqd_t           open_mq[CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES + 1];
156
157  attr.mq_maxmsg  = MAXMSG;
158  attr.mq_msgsize = MSGSIZE;
159
160  Start_Test( "mq_open errors" );
161
162  /*
163   * XXX EINVAL - inappropriate name was given for the message queue
164   */
165
166  /*
167   * EINVAL - Create with negative maxmsg.
168   */
169
170  attr.mq_maxmsg = -1;
171  puts( "Init: mq_open - Create with maxmsg (-1) (EINVAL)" );
172  n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr);
173  fatal_posix_service_pointer_minus_one(
174    (void *)n_mq2, "mq_open error return status" );
175  fatal_posix_service_status( errno, EINVAL,  "mq_open errno EINVAL");
176  attr.mq_maxmsg  = MAXMSG;
177
178  /*
179   * EINVAL - Create withnegative msgsize.
180   */
181
182  attr.mq_msgsize = -1;
183  puts( "Init: mq_open - Create with msgsize (-1) (EINVAL)" );
184  n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr);
185  fatal_posix_service_pointer_minus_one(
186    (void *) n_mq2, "mq_open error return status" );
187  fatal_posix_service_status( errno, EINVAL,  "mq_open errno EINVAL");
188  attr.mq_msgsize = MSGSIZE;
189
190  /*
191   * ENOENT - Open a non-created file.
192   */
193
194  puts( "Init: mq_open - Open new mq without create flag (ENOENT)" );
195  n_mq2 = mq_open( "mq3", O_EXCL | O_RDONLY, 0x777, NULL);
196  fatal_posix_service_pointer_minus_one(
197    (void *) n_mq2, "mq_open error return status" );
198  fatal_posix_service_status( errno, ENOENT,  "mq_open errno ENOENT");
199
200  /*
201   * XXX EINTR  - call was interrupted by a signal
202   */
203
204  /*
205   * ENAMETOOLONG - Give a name greater than PATH_MAX.
206   */
207
208  puts( "Init: mq_open - Open with too long of a name (ENAMETOOLONG)" );
209  n_mq2 = mq_open( Get_Too_Long_Name(), O_CREAT | O_RDONLY, 0x777, NULL );
210  fatal_posix_service_pointer_minus_one(
211    (void *) n_mq2, "mq_open error return status" );
212  fatal_posix_service_status( errno, ENAMETOOLONG, "mq_open errno ENAMETOOLONG");
213
214  /*
215   * XXX - ENAMETOOLONG - Give a name greater than NAME_MAX
216   *       Per implementation not possible.
217   */
218
219  /*
220   * EEXIST - Create an existing queue.
221   */
222
223  puts( "Init: mq_open - Create an Existing mq (EEXIST)" );
224  open_mq[0] = mq_open(
225    Build_Queue_Name(0), O_CREAT | O_RDWR | O_NONBLOCK, 0x777, NULL );
226  assert( open_mq[0] != (-1) );
227
228  n_mq2 = mq_open(
229    Build_Queue_Name(0), O_CREAT | O_EXCL | O_RDONLY, 0x777, NULL);
230  fatal_posix_service_pointer_minus_one(
231    (void *) n_mq2, "mq_open error return status" );
232  fatal_posix_service_status( errno, EEXIST,  "mq_open errno EEXIST");
233
234  status = mq_unlink( Build_Queue_Name(0) );
235  fatal_posix_service_status( status, 0, "mq_unlink message queue");
236
237  status = mq_close( open_mq[0]);
238  fatal_posix_service_status( status, 0, "mq_close message queue");
239
240  /*
241   * Open maximum number of message queues
242   */
243
244  puts( "Init: mq_open - SUCCESSFUL" );
245  for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) {
246    open_mq[i] = mq_open(
247      Build_Queue_Name(i), O_CREAT | O_RDWR | O_NONBLOCK, 0x777, NULL );
248    assert( open_mq[i] != (-1) );
249    assert( open_mq[i] );
250    /*XXX - Isn't there a more general check */
251/* JRS     printf( "mq_open 0x%x %s\n", open_mq[i], Build_Queue_Name(i) ); */
252  }
253
254  /*
255   * XXX EACCES - permission to create is denied.
256   */
257
258  /*
259   * XXX EACCES - queue exists permissions specified by o_flag are denied.
260   */
261
262  /*
263   * XXX EMFILE  - Too many message queues in use by the process
264   */
265
266  /*
267   * ENFILE -  Too many message queues open in the system
268   */
269
270  puts( "Init: mq_open - system is out of resources (ENFILE)" );
271  n_mq2 = mq_open( Build_Queue_Name(i), O_CREAT | O_RDONLY, 0x777, NULL );
272  fatal_posix_service_pointer_minus_one(
273    (void *) n_mq2, "mq_open error return status" );
274  fatal_posix_service_status( errno, ENFILE,  "mq_open errno ENFILE");
275
276  /*
277   * Unlink and Close all queues.
278   */
279
280  puts( "Init: mq_close and mq_unlink (mq3...mqn) - SUCCESSFUL" );
281  for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) {
282
283    status = mq_close( open_mq[i]);
284    fatal_posix_service_status( status, 0, "mq_close message queue");
285
286    status = mq_unlink( Build_Queue_Name(i) );
287    if ( status == -1 )
288      perror( "mq_unlink" );
289    fatal_posix_service_status( status, 0, "mq_unlink message queue");
290    /* JRS printf( "mq_close/mq_unlink 0x%x %s\n", open_mq[i], Build_Queue_Name(i) ); */
291  }
292}
293
294void validate_mq_unlink_error_codes(void)
295{
296  int             status;
297
298  Start_Test( "mq_unlink errors" );
299
300  /*
301   * XXX - EACCES Permission Denied
302   */
303
304  /*
305   * ENAMETOOLONG - Give a name greater than PATH_MAX.
306   */
307
308  puts( "Init: mq_unlink - mq_unlink with too long of a name (ENAMETOOLONG)" );
309  status = mq_unlink( Get_Too_Long_Name() );
310  fatal_posix_service_status( status, -1, "mq_unlink error return status");
311  fatal_posix_service_status( errno, ENAMETOOLONG, "mq_unlink errno ENAMETOOLONG");
312
313  /*
314   * XXX - ENAMETOOLONG - Give a name greater than NAME_MAX
315   *       Per implementation not possible.
316   */
317
318  /*
319   *  ENOENT - Unlink an unopened queue
320   */
321
322  puts( "Init: mq_unlink - A Queue not opened  (ENOENT)" );
323  status = mq_unlink( CLOSED_NAME );
324  fatal_posix_service_status( status, -1, "mq_unlink error return status");
325  fatal_posix_service_status( errno, ENOENT, "mq_unlink errno ENOENT");
326
327  /*
328   * XXX - The following were not listed in the POSIX document as
329   *       possible errors.  Under other commands the EINVAL is
330   *       given for these conditions.
331   */
332
333  /*
334   *  EINVAL - Unlink a queue with no name
335   */
336
337  puts( "Init: mq_unlink (NULL) - EINVAL" );
338  status = mq_unlink( NULL );
339  fatal_posix_service_status( status, -1, "mq_unlink error return status");
340  fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value");
341
342  /*
343   *  EINVAL - Unlink a queue with a null name
344   */
345
346  puts( "Init: mq_unlink (\"\") - EINVAL" );
347  status = mq_unlink( "" );
348  fatal_posix_service_status( status, -1, "mq_unlink error return status");
349  fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value");
350}
351
352void validate_mq_close_error_codes(void)
353{
354  int             status;
355
356  Start_Test( "mq_close errors" );
357
358  /*
359   * EBADF - Close a queue that is not open.
360   */
361
362  puts( "Init: mq_close - unopened queue (EBADF)" );
363  status = mq_close( Test_q[CLOSED].mq );
364  fatal_posix_service_status( status, -1, "mq_close error return status");
365  fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF");
366}
367
368
369void validate_mq_getattr_error_codes(void)
370{
371  struct mq_attr  attr;
372  int             status;
373
374  Start_Test( "mq_getattr errors" );
375
376  /*
377   * EBADF - Get the attributes from a closed queue.
378   */
379
380  puts( "Init: mq_getattr - unopened queue (EBADF)" );
381  status = mq_getattr( Test_q[CLOSED].mq, &attr );
382  fatal_posix_service_status( status, -1, "mq_close error return status");
383  fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF");
384
385  /*
386   * XXX - The following are not listed in the POSIX manual but
387   *       may occur.
388   */
389
390  /*
391   * EINVAL - NULL attributes
392   */
393
394  puts( "Init: mq_getattr - NULL attributes (EINVAL)" );
395  status = mq_getattr( Test_q[RW_QUEUE].mq, NULL );
396  fatal_posix_service_status( status, -1, "mq_close error return status");
397  fatal_posix_service_status( errno, EINVAL, "mq_close errno EINVAL");
398
399}
400
401
402void Send_msg_to_que(
403  int que,
404  int msg
405)
406{
407  Test_Message_t *ptr = &Predefined_Msgs[msg];
408  int             status;
409
410  status = mq_send( Test_q[que].mq, ptr->msg, ptr->size , ptr->priority );
411  fatal_posix_service_status( status, 0, "mq_send valid return status");
412  Test_q[que].count++;
413}
414
415void Show_send_msg_to_que(
416  char *task_name,
417  int   que,
418  int   msg
419)
420{
421  Test_Message_t *ptr = &Predefined_Msgs[msg];
422  printf( "%s mq_send -  to %s msg: %s priority %d\n",
423    task_name, Test_q[que].name, ptr->msg, ptr->priority);
424  Send_msg_to_que( que, msg );
425}
426
427void verify_queues_full(
428  char *task_name
429)
430{
431  int          que;
432
433  /*
434   * Validate that the queues are full.
435   */
436
437  printf( "%s Verify Queues are full\n", task_name );
438  for( que = RW_QUEUE; que < CLOSED; que++ )
439    Validate_attributes( Test_q[que].mq, Test_q[que].oflag, Test_q[que].count );
440
441}
442void verify_queues_empty(
443  char *task_name
444)
445{
446  int             que;
447
448  printf( "%s Verify Queues are empty\n", task_name );
449  for( que = RW_QUEUE; que < CLOSED; que++ )
450    Validate_attributes( Test_q[que].mq, Test_q[que].oflag, 0 );
451}
452
453int fill_message_queues(
454  char *task_name
455)
456{
457  int             msg;
458  int             que;
459
460
461  verify_queues_empty( task_name );
462
463  /*
464   * Fill Queue with predefined messages.
465   */
466
467  printf( "%s Fill Queues with messages\n", task_name );
468  for(msg=0; msg<MAXMSG; msg++){
469    for( que = RW_QUEUE; que < CLOSED; que++ ) {
470      Send_msg_to_que( que, msg );
471    }
472  }
473
474  verify_queues_full( "Init:" );
475  return msg;
476}
477
478
479void Read_msg_from_que(
480  int que,
481  int msg
482)
483{
484  unsigned int    priority;
485  Test_Message_t *ptr;
486  int             status;
487  char            message[100];
488  char            err_msg[100];
489
490  ptr = &Predefined_Msgs[msg];
491  status = mq_receive(Test_q[ que ].mq, message, 100, &priority );
492  Test_q[que].count--;
493
494  sprintf( err_msg, "%s msg %s size failure", Test_q[ que ].name, ptr->msg );
495  fatal_int_service_status( status, ptr->size, err_msg );
496
497  assert( !strcmp( message, ptr->msg ) );
498  strcpy( message, "No Message" );
499
500  sprintf( err_msg,"%s msg %s size failure", Test_q[ que ].name, ptr->msg );
501  fatal_int_service_status(priority, ptr->priority, err_msg );
502}
503
504int empty_message_queues(
505  char *task_name
506)
507{
508  int que;
509  int i;
510
511  printf( "%s Empty all Queues\n", task_name );
512  for( que = RW_QUEUE; que < CLOSED; que++ ) {
513    for(i=0; Test_q[que].count != 0; i++ )
514      Read_msg_from_que( que,  Priority_Order[i] );
515
516    Validate_attributes( Test_q[ que].mq, Test_q[ que ].oflag, 0 );
517  }
518  return 0;
519}
520
521/*
522 * Returns the number of messages queued after the test on the
523 * first queue.
524 */
525
526int validate_mq_send_error_codes(void)
527{
528  int             status;
529  int             i;
530  char           *str;
531
532  Start_Test( "mq_send errors" );
533
534  /*
535   * EBADF - Write to a closed queue.
536   */
537
538  puts( "Init: mq_send - Closed message queue (EBADF)" );
539  status = mq_send( Test_q[CLOSED].mq, "", 1, 0 );
540  fatal_posix_service_status( status, -1, "mq_send error return status");
541  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
542
543  /*
544   * EBADF - Write to a read only  queue.
545   */
546
547  puts( "Init: mq_send - Read only message queue (EBADF)" );
548  status = mq_send( Test_q[ RD_QUEUE ].mq, "", 1, 0 );
549  fatal_posix_service_status( status, -1, "mq_send error return status");
550  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
551
552  /*
553   * XXX - EINTR      Signal interrupted the call.
554   *
555  puts( "Init: mq_send - UNSUCCESSFUL (EINTR)" );
556  status = mq_send( Test_q, "", 0xffff, 0 );
557  fatal_posix_service_status( status, -1, "mq_send error return status");
558  fatal_posix_service_status( errno, E, "mq_send errno E");
559   */
560
561  /*
562   * EINVAL priority is out of range.
563   */
564
565  puts( "Init: mq_send - Priority out of range (EINVAL)" );
566  status = mq_send( Test_q[ RW_QUEUE ].mq, "", 1, MQ_PRIO_MAX + 1 );
567  fatal_posix_service_status( status, -1, "mq_send error return status");
568  fatal_posix_service_status( errno, EINVAL, "mq_send errno EINVAL");
569
570  /*
571   *  EMSGSIZE - Message size larger than msg_len
572   *             Validates that msgsize is stored correctly.
573   */
574
575  puts( "Init: mq_send - Message longer than msg_len (EMSGSIZE)" );
576  status = mq_send( Test_q[ RW_QUEUE ].mq, "", MSGSIZE+1, 0 );
577  fatal_posix_service_status( status, -1, "mq_send error return status");
578  fatal_posix_service_status( errno, EMSGSIZE, "mq_send errno EMSGSIZE");
579
580  i = fill_message_queues( "Init:" );
581
582  /*
583   * ENOSYS - send not supported
584  puts( "Init: mq_send - Blocking Queue overflow (ENOSYS)" );
585  status = mq_send( n_mq1, Predefined_Msgs[i], 0, 0 );
586  fatal_posix_service_status( status, -1, "mq_send error return status");
587  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
588
589  status = mq_close( n_mq1 );
590  fatal_posix_service_status( status, 0, "mq_close message queue");
591
592  status = mq_unlink( "read_only" );
593  fatal_posix_service_status( status, 0, "mq_unlink message queue");
594   */
595
596  /*
597   * EAGAIN - O_NONBLOCK and message queue is full.
598   */
599
600  puts( "Init: mq_send - on a FULL non-blocking queue with (EAGAIN)" );
601  str = Predefined_Msgs[i].msg;
602  status = mq_send(Test_q[RW_QUEUE].mq, str, 0, 0 );
603  fatal_posix_service_status( status, -1, "mq_send error return status");
604  fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN");
605
606  return i-1;
607}
608
609void validate_mq_receive_error_codes(void)
610{
611  int            status;
612  char           message[100];
613  unsigned int   priority;
614
615  Start_Test( "mq_receive errors"  );
616
617  /*
618   * EBADF - Not A Valid Message Queue
619   */
620
621  puts( "Init: mq_receive - Unopened message queue (EBADF)" );
622  status = mq_receive( Test_q[CLOSED].mq, message, 100, &priority );
623  fatal_posix_service_status( status, -1, "mq_ error return status");
624  fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
625
626  /*
627   * EBADF - Queue not opened to read
628   */
629
630  puts( "Init: mq_receive - Write only queue (EBADF)" );
631  status = mq_receive( Test_q[WR_QUEUE].mq, message, 100, &priority  );
632  fatal_posix_service_status( status, -1, "mq_ error return status");
633  fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
634
635  /*
636   * EMSGSIZE - Size is less than the message size attribute
637   */
638
639  puts( "Init: mq_receive - Size is less than the message (EMSGSIZE)" );
640  status = mq_receive(
641    Test_q[RW_QUEUE].mq, message, Predefined_Msgs[0].size-1, &priority );
642  fatal_posix_service_status( status, -1, "mq_ error return status");
643  fatal_posix_service_status( errno, EMSGSIZE, "mq_receive errno EMSGSIZE");
644
645
646  /*
647   * EAGAIN - O_NONBLOCK and Queue is empty
648   */
649  verify_queues_full( "Init:" );
650  empty_message_queues( "Init:" );
651
652  puts( "Init: mq_receive - Queue is empty (EAGAIN)" );
653  status = mq_receive( Test_q[RW_QUEUE].mq, message, 100, &priority );
654  fatal_posix_service_status( status, -1, "mq_ error return status");
655  fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN");
656
657  /*
658   * XXX - EINTR - Interrupted by a signal
659   */
660
661  /*
662   * XXX - EBADMSG - a data corruption problem.
663   */
664
665  /*
666   * XXX - ENOSYS - mq_receive not supported
667   */
668}
669
670void verify_open_functionality(void)
671{
672#if 0
673  mqd_t           n_mq;
674#endif
675
676  Start_Test( "mq_open functionality" );
677
678  /*
679   * Validate a second open returns the same message queue.
680   */
681
682#if 0
683  puts( "Init: mq_open - Open an existing mq ( same id )" );
684  n_mq = mq_open( RD_NAME, 0 );
685  fatal_posix_service_status(
686  assert( n_mq == Test_q[RD_QUEUE].mq );
687#endif
688}
689
690void verify_unlink_functionality(void)
691{
692  mqd_t           n_mq;
693  int             status;
694
695  Start_Test( "mq_unlink functionality" );
696
697  /*
698   * Unlink the message queue, then verify an open of the same name produces a
699   * different message queue.
700   */
701
702  puts( "Init: Unlink and Open without closing SUCCESSFUL" );
703  status = mq_unlink( DEFAULT_NAME );
704  fatal_posix_service_status( status, 0, "mq_unlink locked message queue");
705
706  n_mq = mq_open( DEFAULT_NAME, DEFAULT_ATTR, 0x777, NULL );
707  assert( n_mq != (-1) );
708  assert( n_mq != Test_q[ DEFAULT_RW ].mq );
709
710
711  status = mq_unlink( DEFAULT_NAME );
712  fatal_posix_service_status( status, 0, "mq_unlink locked message queue");
713  status = mq_close( Test_q[ DEFAULT_RW ].mq );
714  fatal_posix_service_status( status, 0, "mq_close message queue");
715
716  Test_q[ DEFAULT_RW ].mq = n_mq;
717}
718
719void verify_close_functionality(void)
720{
721  int i;
722  int status;
723  Start_Test( "Unlink and Close All Files"  );
724  for (i=0; i<DEFAULT_RW; i++) {
725
726    status = mq_unlink( Get_Queue_Name(i) );
727    fatal_posix_service_status( status, 0, "mq_unlink message queue");
728
729    status = mq_close( Test_q[i].mq );
730    fatal_posix_service_status( status, 0, "mq_close message queue");
731  }
732}
733
734
735void verify_timed_send_queue(
736  int  que,
737  int  is_blocking
738)
739{
740  struct timespec timeout;
741  struct timeval  tv1, tv2, tv3;
742  struct timezone tz1, tz2;
743  int              len;
744  int              status;
745  char            *msg;
746
747  printf( "Init: mq_timedsend - on queue %s ", Test_q[que].name);
748  len = Predefined_Msgs[MAXMSG].size;
749  msg = Predefined_Msgs[MAXMSG].msg;
750
751  gettimeofday( &tv1, &tz1 );
752  timeout.tv_sec  = tv1.tv_sec + 1;
753  timeout.tv_nsec = tv1.tv_usec * 1000;
754
755  status = mq_timedsend( Test_q[que].mq, msg, len , 0, &timeout );
756
757  gettimeofday( &tv2, &tz2 );
758  tv3.tv_sec  = tv2.tv_sec - tv1.tv_sec;
759  tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
760
761  if ( is_blocking ) { /* Don't verify the non-blocking queue */
762    fatal_int_service_status( status, -1, "mq_timedsend status" );
763    fatal_posix_service_status( errno, ETIMEDOUT,  "errno ETIMEDOUT" );
764  }
765
766  printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
767
768  if ( que == DEFAULT_RW )
769    Test_q[que].count++;
770}
771
772void verify_timed_send(void)
773{
774  int              que;
775
776  Start_Test( "mq_timedsend"  );
777
778  for( que = RW_QUEUE; que < CLOSED; que++ ) {
779    if ( que == BLOCKING )
780      verify_timed_send_queue( que, 1 );
781    else
782      verify_timed_send_queue( que, 0 );
783  }
784}
785
786void verify_timed_receive_queue(
787  char *task_name,
788  int   que,
789  int   is_blocking
790)
791{
792  char message[ 100 ];
793  unsigned int priority;
794  struct timespec tm;
795  struct timeval  tv1, tv2, tv3;
796  struct timezone tz1, tz2;
797  int              status;
798
799  printf(
800    "Init: %s mq_timedreceive - on queue %s ",
801    task_name,
802    Test_q[que].name
803  );
804
805  gettimeofday( &tv1, &tz1 );
806  tm.tv_sec  = tv1.tv_sec + 1;
807  tm.tv_nsec = tv1.tv_usec * 1000;
808
809  status = mq_timedreceive( Test_q[ que ].mq, message, 100, &priority, &tm );
810
811  gettimeofday( &tv2, &tz2 );
812  tv3.tv_sec  = tv2.tv_sec - tv1.tv_sec;
813  tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
814
815  fatal_int_service_status( status, -1, "mq_timedreceive status");
816  if ( is_blocking )
817    fatal_posix_service_status( errno, ETIMEDOUT,  "errno ETIMEDOUT");
818  printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
819
820}
821
822void verify_timed_receive(void)
823{
824  int  que;
825
826  Start_Test( "mq_timedreceive"  );
827
828  for( que = RW_QUEUE; que < CLOSED; que++ ) {
829    if (( que == BLOCKING ) || ( que == DEFAULT_RW ))
830      verify_timed_receive_queue( "Init:", que, 1 );
831    else
832      verify_timed_receive_queue( "Init:", que, 0 );
833  }
834}
835
836#if (0)
837void verify_set_attr(void)
838{
839  struct mq_attr save_attr[ NUMBER_OF_TEST_QUEUES ];
840  struct mq_attr attr;
841  int            i;
842  int            status;
843
844  attr.mq_maxmsg  = 0;
845  attr.mq_msgsize = 0;
846
847  Start_Test( "mq_setattr"  );
848
849  puts( "Init: set_attr all queues to blocking" );
850  for(i=0; i<CLOSED; i++) {
851    attr.mq_flags =  Test_q[i].oflag & (~O_NONBLOCK );
852    status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] );
853    fatal_int_service_status( status, 0, "mq_setattr valid return status");
854
855    Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 );
856  }
857
858  for( i = RW_QUEUE; i < CLOSED; i++ ) {
859    verify_timed_receive_queue( "Init:", i, 1 );
860  }
861
862  for(i=0; i<CLOSED; i++) {
863    attr.mq_flags =  Test_q[i].oflag & (~O_NONBLOCK );
864    status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL );
865    fatal_int_service_status( status, 0, "mq_setattr valid return status");
866
867    Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 );
868  }
869}
870#endif
871
872void wait_for_signal(
873  sigset_t     *waitset,
874  int           sec,
875  int           expect_signal
876)
877{
878  siginfo_t         siginfo;
879  int               status;
880  struct timespec   timeout;
881  int               signo;
882
883  siginfo.si_code = -1;
884  siginfo.si_signo = -1;
885  siginfo.si_value.sival_int = -1;
886
887  timeout.tv_sec = sec;
888  timeout.tv_nsec = 0;
889
890  status = sigemptyset( waitset );
891  assert( !status );
892
893  status = sigaddset( waitset, SIGUSR1 );
894  assert( !status );
895
896  printf( "waiting on any signal for %d seconds.\n", sec );
897  signo = sigtimedwait( waitset, &siginfo, &timeout );
898  if (expect_signal) {
899    fatal_int_service_status( signo, SIGUSR1, "got SISUSR1" );
900  } else {
901    fatal_int_service_status( signo, -1, "error return status");
902    fatal_posix_service_status( errno, EAGAIN, "errno EAGAIN");
903  }
904}
905
906void verify_notify(void)
907{
908  struct sigevent event;
909  int             status;
910  timer_t         timer_id;
911  sigset_t        set;
912
913  Start_Test( "mq_notify"  );
914
915  /* timer create */
916  event.sigev_notify = SIGEV_SIGNAL;
917  event.sigev_signo  = SIGUSR1;
918  if (timer_create (CLOCK_REALTIME, &event, &timer_id) == -1)
919    fatal_posix_service_status( errno, 0,  "errno ETIMEDOUT");
920
921  /* block the timer signal */
922  sigemptyset( &set );
923  sigaddset( &set, SIGUSR1 );
924  pthread_sigmask( SIG_BLOCK, &set, NULL );
925
926  /*
927   * EBADF - Not A Valid Message Queue
928   */
929
930  puts( "Init: mq_notify - Unopened message queue (EBADF)" );
931  status = mq_notify( Test_q[CLOSED].mq, NULL );
932  fatal_posix_service_status( status, -1, "mq_ error return status");
933  fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
934
935  /*
936   * Create ...
937   */
938
939  /*
940   * XXX setup notification
941   */
942  printf( "_____mq_notify - notify when %s gets a message\n",RW_NAME);
943  status = mq_notify( Test_q[RW_QUEUE].mq, &event );
944  fatal_posix_service_status( status, 0, "mq_notify valid status");
945  wait_for_signal( &set, 3, 0 );
946
947  /*
948   * Send and verify signal occurs and registration is removed.
949   */
950
951  puts( "Init: Verify Signal when send" );
952  Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
953  wait_for_signal( &set, 3, 1 );
954  Read_msg_from_que( RW_QUEUE, 0 );
955
956  puts( "Init: Verify No Signal when send" );
957  Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
958  wait_for_signal( &set, 3, 0 );
959  Read_msg_from_que( RW_QUEUE, 0 );
960
961  /*
962   * EBUSY - Already Registered
963   */
964
965  printf( "____mq_notify - notify when %s gets a message\n",RD_NAME);
966  status = mq_notify( Test_q[RW_QUEUE].mq, &event );
967  fatal_posix_service_status( status, 0, "mq_notify valid status");
968  wait_for_signal( &set, 3, 0 );
969
970  puts( "Init: mq_notify -  (EBUSY)" );
971  status = mq_notify( Test_q[RW_QUEUE].mq, &event );
972  fatal_posix_service_status( status, -1, "mq_notify error return status");
973  fatal_posix_service_status( errno, EBUSY, "mq_notify errno EBUSY");
974
975  /*
976   * Verify NULL removes registration.
977   */
978
979  puts( "Init: mq_notify - Remove notification with null" );
980  status = mq_notify( Test_q[RW_QUEUE].mq, NULL );
981  fatal_posix_service_status( status, 0, "mq_notify valid status");
982
983  puts( "Init: Verify No Signal when send" );
984  Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
985  wait_for_signal( &set, 3, 0 );
986  Read_msg_from_que( RW_QUEUE, 0 );
987
988}
989
990void verify_with_threads(void)
991{
992  int               status;
993  pthread_t         id;
994  Test_Message_t   *ptr;
995#if 0
996  unsigned int      priority;
997  char              message[100];
998#endif
999
1000
1001#if 0
1002  /*
1003   * Create a task then block until the task sends the message.
1004   * Task tests set attributes so one queue will have a thread
1005   * blocked while attributes are changed.
1006   */
1007
1008  Start_Test( "multi-thread Task 4 Receive Test"  );
1009  status = pthread_create( &id, NULL, Task_4, NULL );
1010  assert( !status );
1011  puts( "Init: mq_receive - Empty queue changes to non-blocking (EAGAIN)" );
1012  status = mq_receive( Test_q[BLOCKING].mq, message, 100, &priority );
1013  fatal_int_service_status( status, -1, "mq_receive error return status");
1014  fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN");
1015  print_current_time( "Init: ", "" );
1016#endif
1017  /*
1018   * Create a task then block until the task sends the message.
1019   * Task tests set attributes so one queue will have a thread
1020   * blocked while attributes are changed.
1021   */
1022
1023  Start_Test( "multi-thread Task 1 Test"  );
1024  status = pthread_create( &id, NULL, Task_1, NULL );
1025  assert( !status );
1026  Read_msg_from_que(  BLOCKING, 0 ); /* Block until init writes */
1027  print_current_time( "Init: ", "" );
1028
1029#if 0
1030  /*
1031   * Fill the queue then create a task then block until the task receives a message.
1032   * Task tests set attributes so one queue will have a thread
1033   * blocked while attributes are changed.
1034   */
1035
1036  Start_Test( "multi-thread Task 4 Send Test"  );
1037  fill_message_queues( "Init:" );
1038  status = pthread_create( &id, NULL, Task_4, NULL );
1039  assert( !status );
1040  puts( "Init: mq_send - Full queue changes to non-blocking (EAGAIN)" );
1041  status = mq_send(Test_q[BLOCKING].mq, message, 0, 0 );
1042  fatal_posix_service_status( status, -1, "mq_send error return status");
1043  fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN");
1044  verify_queues_full( "Init:" );
1045  empty_message_queues( "Init:" );
1046#endif
1047  /*
1048   * Create a task then block until the task reads a message.
1049   */
1050
1051  Start_Test( "multi-thread Task 2 Test"  );
1052  fill_message_queues( "Init:" );
1053  status = pthread_create( &id, NULL, Task_2, NULL );
1054  assert( !status );
1055  Show_send_msg_to_que( "Init:", BLOCKING, Priority_Order[0] );
1056  print_current_time( "Init: ", "" );
1057  verify_queues_full( "Init:" );
1058  empty_message_queues( "Init:" );
1059
1060  /*
1061   * Create a task then block until it deletes and closes all queues.
1062   *     EBADF - Queue unlinked and closed while blocked
1063   */
1064
1065  Start_Test( "multi-thread Task 3 Test"  );
1066  fill_message_queues( "Init:" );
1067  status = pthread_create( &id, NULL, Task_3, NULL );
1068  assert( !status );
1069  puts( "Init: mq_send - Block while thread deletes queue (EBADF)" );
1070  ptr = &Predefined_Msgs[0];
1071  status = mq_send( Test_q[BLOCKING].mq, ptr->msg, ptr->size , ptr->priority );
1072  fatal_posix_service_status( status, -1, "mq_send error return status");
1073  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
1074
1075}
1076
1077void validate_mq_setattr(void)
1078{
1079  struct mq_attr  attr;
1080  struct mq_attr  save_attr[ NUMBER_OF_TEST_QUEUES ];
1081  int             status;
1082  int            i;
1083
1084  /*
1085   * EBADF - Get the attributes from a closed queue.
1086   */
1087
1088  puts( "Task1:mq_setattr - unopened queue (EBADF)" );
1089  status = mq_setattr( Test_q[CLOSED].mq, &attr, NULL );
1090  fatal_posix_service_status( status, -1, "mq_setattr error return status");
1091  fatal_posix_service_status( errno, EBADF, "mq_setattr errno EBADF");
1092
1093  /*
1094   * XXX - The following are not listed in the POSIX manual but
1095   *       may occur.
1096   */
1097
1098  /*
1099   * EINVAL - NULL attributes
1100   */
1101
1102  puts( "Task1:mq_setattr - NULL attributes (EINVAL)" );
1103  status = mq_setattr( Test_q[RW_QUEUE].mq, NULL, NULL );
1104  fatal_posix_service_status( status, -1, "mq_setattr error return status");
1105  fatal_posix_service_status( errno, EINVAL, "mq_setattr errno EINVAL");
1106
1107  /*
1108   * Verify change queues to blocking, by verifying all queues block
1109   * for a timed receive.
1110   */
1111
1112  puts( "Init: set_attr all queues to blocking" );
1113  for(i=0; i<CLOSED; i++) {
1114    attr.mq_flags =  Test_q[i].oflag & (~O_NONBLOCK );
1115    status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] );
1116    fatal_int_service_status( status, 0, "mq_setattr valid return status");
1117    Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 );
1118  }
1119  for( i = RW_QUEUE; i < CLOSED; i++ ) {
1120    verify_timed_receive_queue( "Init:", i, 1 );
1121  }
1122
1123  /*
1124   * Restore restore all queues to their old attribute.
1125   */
1126
1127  for(i=0; i<CLOSED; i++) {
1128    status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL );
1129    fatal_int_service_status( status, 0, "mq_setattr valid return status");
1130    Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 );
1131  }
1132}
1133
1134void verify_timedout_mq_timedreceive(
1135  char *task_name,
1136  int   que,
1137  int   is_blocking
1138)
1139{
1140  char message[ 100 ];
1141  unsigned int priority;
1142  struct timespec tm;
1143  struct timeval  tv1, tv2, tv3;
1144  struct timezone tz1, tz2;
1145  int              status;
1146
1147  printf(
1148    "Init: %s verify_timedout_mq_timedreceive - on queue %s ",
1149    task_name,
1150    Test_q[que].name
1151  );
1152
1153  gettimeofday( &tv1, &tz1 );
1154  tm.tv_sec  = tv1.tv_sec - 1;
1155  tm.tv_nsec = tv1.tv_usec * 1000;
1156
1157  status = mq_timedreceive( Test_q[ que ].mq, message, 100, &priority, &tm );
1158
1159  gettimeofday( &tv2, &tz2 );
1160  tv3.tv_sec  = tv2.tv_sec - tv1.tv_sec;
1161  tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
1162
1163  fatal_int_service_status( status, -1, "mq_timedreceive status");
1164
1165/* FIXME: This is wrong. */
1166  printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
1167}
1168
1169void verify_mq_receive(void)
1170{
1171  int  que;
1172
1173  Start_Test( "mq_timedout_receive"  );
1174
1175  for( que = RW_QUEUE; que < CLOSED; que++ ) {
1176    if (( que == BLOCKING ) || ( que == DEFAULT_RW ))
1177      break;
1178    else
1179      verify_timedout_mq_timedreceive( "Init:", que, 0 );
1180  }
1181}
1182
1183void verify_timedout_mq_timedsend(
1184  int  que,
1185  int  is_blocking
1186)
1187{
1188  struct timespec timeout;
1189  struct timeval  tv1, tv2, tv3;
1190  struct timezone tz1, tz2;
1191  int              len;
1192  int              status;
1193  char            *msg;
1194
1195  printf( "Init: verify_timedout_mq_timedsend - on queue %s ", Test_q[que].name);
1196  len = Predefined_Msgs[MAXMSG].size;
1197  msg = Predefined_Msgs[MAXMSG].msg;
1198
1199  gettimeofday( &tv1, &tz1 );
1200  timeout.tv_sec  = tv1.tv_sec - 1;
1201  timeout.tv_nsec = tv1.tv_usec * 1000;
1202
1203  status = mq_timedsend( Test_q[que].mq, msg, len , 0, &timeout );
1204
1205  gettimeofday( &tv2, &tz2 );
1206  tv3.tv_sec  = tv2.tv_sec - tv1.tv_sec;
1207  tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
1208
1209  printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
1210
1211  if ( que == DEFAULT_RW )
1212    Test_q[que].count++;
1213}
1214
1215void verify_mq_send(void)
1216{
1217  int              que;
1218
1219  Start_Test( "verify_timedout_mq_timedsend"  );
1220
1221  for( que = RW_QUEUE; que < CLOSED; que++ ) {
1222    if ( que == BLOCKING )
1223      verify_timedout_mq_timedsend( que, 1 );
1224    else
1225      verify_timedout_mq_timedsend( que, 0 );
1226  }
1227}
1228
1229void *POSIX_Init(
1230  void *argument
1231)
1232{
1233  puts( "\n\n*** POSIX MESSAGE QUEUE TEST ***" );
1234
1235  validate_mq_open_error_codes( );
1236  open_test_queues();
1237  validate_mq_unlink_error_codes();
1238  validate_mq_close_error_codes();
1239  verify_unlink_functionality();
1240  validate_mq_setattr( );
1241  validate_mq_send_error_codes();
1242  validate_mq_getattr_error_codes();
1243  verify_timed_send();
1244  validate_mq_receive_error_codes();
1245  verify_timed_receive();
1246  verify_open_functionality();
1247  verify_notify();
1248  verify_with_threads();
1249  verify_mq_receive();
1250  verify_mq_send();
1251 
1252  puts( "*** END OF POSIX MESSAGE QUEUE TEST ***" );
1253  rtems_test_exit( 0 );
1254
1255  return NULL; /* just so the compiler thinks we returned something */
1256}
1257
1258
1259void *Task_1 (
1260  void *argument
1261)
1262{
1263  /* Block Waiting for a message */
1264
1265  print_current_time( "Task_1: ", "" );
1266
1267  Show_send_msg_to_que( "Task_1:", BLOCKING, 0 );
1268
1269  puts( "Task_1: pthread_exit" );
1270  pthread_exit( NULL );
1271
1272  /* switch to Init */
1273
1274  assert( 0 );
1275  return NULL; /* just so the compiler thinks we returned something */
1276}
1277
1278void *Task_2(
1279  void *argument
1280)
1281{
1282  print_current_time( "Task_2: ", "" );
1283
1284
1285  /* Block waiting to send a message */
1286
1287  verify_queues_full( "Task_2:" );
1288  Read_msg_from_que( BLOCKING, Priority_Order[0] ); /* Cause context switch */
1289
1290  puts( "Task_2: pthread_exit" );
1291  pthread_exit( NULL );
1292
1293     /* switch to Init */
1294
1295  return NULL; /* just so the compiler thinks we returned something */
1296}
1297
1298void *Task_3 (
1299  void *argument
1300)
1301{
1302
1303  print_current_time( "Task_3: ", "" );
1304
1305  /*
1306   * close and unlink all queues.
1307   */
1308
1309  verify_close_functionality();
1310  puts( "Task_3: pthread_exit" );
1311  pthread_exit( NULL );
1312
1313     /* switch to Init */
1314
1315  return NULL; /* just so the compiler thinks we returned something */
1316
1317}
1318
1319void *Task_4 (
1320  void *argument
1321)
1322{
1323  struct mq_attr  attr;
1324  int             status;
1325  int             count;
1326
1327  print_current_time( "Task_4: ", "" );
1328
1329  /*
1330   * Set the count to the number of messages in the queue.
1331   */
1332
1333  status = mq_getattr( Test_q[BLOCKING].mq, &attr );
1334  fatal_posix_service_status( status, 0, "mq_getattr valid return status");
1335  count = attr.mq_curmsgs;
1336
1337  puts("Task_4: Set queue to non-blocking");
1338  attr.mq_flags =  Test_q[BLOCKING].oflag | O_NONBLOCK;
1339  status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL );
1340  fatal_int_service_status( status, 0, "mq_setattr valid return status");
1341  Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count );
1342
1343  puts("Task_4: Return queue to blocking");
1344  attr.mq_flags =  Test_q[BLOCKING].oflag;
1345  status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL );
1346  fatal_int_service_status( status, 0, "mq_setattr valid return status");
1347  Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count );
1348
1349  puts( "Task_4: pthread_exit" );
1350  pthread_exit( NULL );
1351
1352     /* switch to Init */
1353
1354  return NULL; /* just so the compiler thinks we returned something */
1355
1356}
1357
1358void *Task_5 (
1359  void *argument
1360)
1361{
1362
1363  print_current_time( "Task_5: ", "" );
1364
1365  puts( "Task_5: pthread_exit" );
1366  pthread_exit( NULL );
1367
1368     /* switch to Init */
1369
1370  return NULL; /* just so the compiler thinks we returned something */
1371
1372}
1373
1374void *Task_ (
1375  void *argument
1376)
1377{
1378
1379  print_current_time( "Task_: ", "" );
1380
1381  puts( "Task_: pthread_exit" );
1382  pthread_exit( NULL );
1383
1384     /* switch to Init */
1385
1386  return NULL; /* just so the compiler thinks we returned something */
1387
1388}
Note: See TracBrowser for help on using the repository browser.