source: rtems/testsuites/psxtests/psxsem01/init.c @ 9a4eca5

5
Last change on this file since 9a4eca5 was d887c1b, checked in by Sebastian Huber <sebastian.huber@…>, on 05/25/16 at 12:28:34

posix: Fix sem_init() with too large initial value

Close #2721.

  • Property mode set to 100644
File size: 12.7 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2012.
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.org/license/LICENSE.
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#include <sched.h>
15#include <semaphore.h>
16#include <errno.h>
17#include <fcntl.h>
18#include <limits.h>
19#include <time.h>
20#include <tmacros.h>
21#include <pmacros.h>
22#include "test_support.h"
23
24const char rtems_test_name[] = "PSXSEM 1";
25
26/* forward declarations to avoid warnings */
27void *POSIX_Init(void *argument);
28
29#define MAX_SEMS  10
30
31static void *sem_wait_task(void *arg)
32{
33  sem_t *sem;
34  int    rv;
35
36  sem = arg;
37
38  rv = sem_wait( sem );
39  rtems_test_assert( rv == 0 );
40
41  errno = 0;
42  rv = sem_wait( sem );
43  rtems_test_assert( rv == -1 );
44  rtems_test_assert( errno == EINVAL );
45
46  return NULL;
47}
48
49static void test_sem_wait_during_delete(void)
50{
51  sem_t     sem;
52  int       rv;
53  pthread_t th;
54  int       eno;
55  int       val;
56
57  rv = sem_init( &sem, 0, 1 );
58  rtems_test_assert( rv == 0 );
59
60  eno = pthread_create( &th, NULL, sem_wait_task, &sem );
61  rtems_test_assert( eno == 0 );
62
63  rv = sem_getvalue( &sem, &val );
64  rtems_test_assert( rv == 0 );
65  rtems_test_assert( val == 1 );
66
67  sched_yield();
68
69  rv = sem_getvalue( &sem, &val );
70  rtems_test_assert( rv == 0 );
71  rtems_test_assert( val == 0 );
72
73  rv = sem_destroy( &sem );
74  rtems_test_assert( rv == 0 );
75
76  eno = pthread_join( th, NULL );
77  rtems_test_assert( eno == 0 );
78}
79
80static void test_sem_post_overflow(void)
81{
82  sem_t sem;
83  int   rv;
84  int   val;
85
86  rv = sem_init( &sem, 0, SEM_VALUE_MAX );
87  rtems_test_assert( rv == 0 );
88
89  rv = sem_getvalue( &sem, &val );
90  rtems_test_assert( rv == 0 );
91  rtems_test_assert( val == (int) SEM_VALUE_MAX );
92
93  errno = 0;
94  rv = sem_post( &sem );
95  rtems_test_assert( rv == -1 );
96  rtems_test_assert( errno == EOVERFLOW );
97
98  rv = sem_getvalue( &sem, &val );
99  rtems_test_assert( rv == 0 );
100  rtems_test_assert( val == (int) SEM_VALUE_MAX );
101
102  rv = sem_wait( &sem );
103  rtems_test_assert( rv == 0 );
104
105  rv = sem_post( &sem );
106  rtems_test_assert( rv == 0 );
107
108  rv = sem_destroy( &sem );
109  rtems_test_assert( rv == 0 );
110}
111
112static void test_sem_init_too_large_inital_value(void)
113{
114  sem_t sem;
115  int   rv;
116
117  errno = 0;
118  rv = sem_init( &sem, 0, SEM_VALUE_MAX + 1 );
119  rtems_test_assert( rv == -1 );
120  rtems_test_assert( errno == EINVAL );
121}
122
123void *POSIX_Init(
124  void *argument
125)
126{
127  int             status;
128  int             value;
129  int             i;
130  sem_t           sems[MAX_SEMS];
131  sem_t           sem2;
132  sem_t           *n_sem1;
133  sem_t           *n_sem2;
134  struct timespec waittime;
135  char            failure_msg[80];
136
137  TEST_BEGIN();
138
139  puts( "Init: sem_init - UNSUCCESSFUL (EINVAL)" );
140  status = sem_init(NULL, 0, 1);
141  fatal_posix_service_status( status, -1, "sem_init error return status");
142  fatal_posix_service_status( errno, EINVAL, "sem_init errorno EINVAL" );
143
144  puts( "Init: sem_init - SUCCESSFUL" );
145  for (i = 0; i < MAX_SEMS; i++) {
146    status = sem_init(&sems[i], 0, i);
147    sprintf(failure_msg, "sem_init %d", i );
148    fatal_posix_service_status( status, 0, failure_msg);
149  }
150  puts( "Init: sem_init - UNSUCCESSFUL (ENOSPC)" );
151  status = sem_init(&sem2, 0, 1);
152  fatal_posix_service_status( status, -1, "sem_init error return status");
153  fatal_posix_service_status( errno, ENOSPC, "sem_init errorno ENOSPC" );
154
155  puts( "Init: sem_init - UNSUCCESSFUL (ENOSYS -- pshared not supported)" );
156  status = sem_init(&sem2, 1, 1);
157  fatal_posix_service_status( status, -1, "sem_init error return status");
158  fatal_posix_service_status( errno, ENOSYS, "sem_init errno set to ENOSYS");
159
160  puts( "Init: sem_getvalue - SUCCESSFUL ");
161  for (i = 0; i < MAX_SEMS; i++) {
162    status = sem_getvalue(&sems[i], &value);
163    sprintf( failure_msg, "sem_getvalue %d", i );
164    fatal_posix_service_status( status, 0, failure_msg );
165    fatal_posix_service_status( value, i, "sem_getvalue correct value" );
166  }
167  puts( "Init: sem_getvalue - UNSUCCESSFUL ");
168  status = sem_getvalue(&sem2, &value);
169  fatal_posix_service_status( status, -1, "sem_getvalue error return status");
170  fatal_posix_service_status( errno, EINVAL, "sem_getvalue errno EINVAL");
171
172  puts( "Init: sem_destroy - SUCCESSFUL" );
173  status = sem_destroy(&sems[0]);
174  fatal_posix_service_status( status, 0, "sem_destroy semaphore 0");
175
176  puts( "Init: sem_destroy - UNSUCCESSFUL (EINVAL)" );
177  status = sem_destroy(&sem2);
178  fatal_posix_service_status( status, -1, "sem_destroy error return status");
179  fatal_posix_service_status( errno, EINVAL, "sem_destroy errno EINVAL");
180
181  puts( "Init: sem_wait - SUCCESSFUL" );
182  status = sem_wait(&sems[1]);
183  fatal_posix_service_status( status, 0, "sem_wait semaphore 1");
184  /* sem[1].count = 0 */
185
186  puts( "Init: sem_wait - UNSUCCESSFUL (EINVAL)" );
187  status = sem_wait(&sem2);
188  fatal_posix_service_status( status, -1, "sem_wait error return status");
189  fatal_posix_service_status( errno, EINVAL, "sem_wait errno EINVAL");
190
191  puts( "Init: sem_post - SUCCESSFUL" );
192  status = sem_post(&sems[1]);
193  fatal_posix_service_status( status, 0, "sem_post semaphore 1");
194  /* sem[1].count = 1 */
195
196  puts( "Init: sem_wait - SUCCESSFUL (after a sem_post)" );
197  status = sem_wait(&sems[1]);
198  fatal_posix_service_status( status, 0, "sem_wait semaphore 1");
199  /* sem[1].count = 0 */
200
201  puts( "Init: sem_trywait - SUCCESSFUL" );
202  status = sem_trywait(&sems[2]);
203  fatal_posix_service_status( status, 0, "sem_trywait semaphore 2");
204  /* sem[2].count = 1 */
205
206  puts( "Init: sem_trywait - UNSUCCESSFUL (EAGAIN)" );
207  status = sem_trywait(&sems[1]);
208  fatal_posix_service_status( status, -1, "sem_trywait error return status");
209  fatal_posix_service_status( errno, EAGAIN, "sem_trywait errno EAGAIN");
210  /* sem[1].count = 0 */
211
212  puts( "Init: sem_trywait - UNSUCCESSFUL (EINVAL)" );
213  status = sem_trywait(&sem2);
214  fatal_posix_service_status( status, -1, "sem_trywait error return status");
215  fatal_posix_service_status( errno, EINVAL, "sem_trywait errno EINVAL");
216
217#if 0
218  status = sem_post(&sems[2]);
219  fatal_posix_service_status( status, 0, "sem_post semaphore 2");
220  /* sem[2].count = 2 */
221#else
222  /* sem[2].count = 1 */
223#endif
224
225  puts( "Init: sem_timedwait - SUCCESSFUL" );
226  waittime.tv_sec = time(NULL) + 1;
227  waittime.tv_nsec = 100;
228  status = sem_timedwait(&sems[2], &waittime);
229  fatal_posix_service_status( status, 0, "sem_timedwait semaphore 2");
230  /* sem[2].count = 0 */
231
232  puts( "Init: sem_timedwait - UNSUCCESSFUL (ETIMEDOUT)" );
233  status = sem_timedwait(&sems[2], &waittime);
234  fatal_posix_service_status( status, -1, "sem_timedwait error return status");
235  fatal_posix_service_status(
236    errno, ETIMEDOUT, "sem_timedwait errno ETIMEDOUT");
237
238  /*
239   * To do this case, we must be blocking when we want the semaphore.
240   * POSIX doesn't want you to check the error if you can get the resource.
241   */
242
243#if 1
244  puts( "Init: sem_timedwait - UNSUCCESSFUL (EINVAL) -- skipping" );
245#else
246  puts( "Init: sem_timedwait - UNSUCCESSFUL (EINVAL)" );
247  waittime.tv_sec = 0;
248  waittime.tv_nsec = 0x7FFFFFFF;
249  status = sem_timedwait(&sems[2], &waittime);
250  fatal_posix_service_status( status, -1, "sem_timedwait error return status");
251  fatal_posix_service_status( errno, EINVAL, "sem_init errno EINVAL");
252#endif
253
254  puts( "Init: sem_post - UNSUCCESSFUL (EINVAL)" );
255  status = sem_post(&sem2);
256  fatal_posix_service_status( status, -1, "sem_post error return status");
257  fatal_posix_service_status( errno, EINVAL, "sem_post errno EINVAL");
258
259  puts( "Init: sem_destroy - SUCCESSFUL" );
260  for (i = 1; i < MAX_SEMS; i++) {
261    status = sem_destroy(&sems[i]);
262    sprintf( failure_msg, "sem_destroy %d", i );
263    fatal_posix_service_status( status, 0, failure_msg );
264  }
265
266  /* Modes are currently unsupported */
267
268  /*
269   * Validate all sem_open return paths.
270   */
271
272  puts( "Init: sem_open - UNSUCCESSFUL (ENAMETOOLONG)" );
273  n_sem1 = sem_open(Get_Too_Long_Name(), O_CREAT, 0777, 1 );
274  fatal_posix_sem( n_sem1, "sem_open error return status" );
275  fatal_posix_service_status(
276    errno, ENAMETOOLONG, "sem_open errorno ENAMETOOLONG" );
277
278  puts( "Init: sem_open - sem1 SUCCESSFUL" );
279  n_sem1 = sem_open( "sem1",O_CREAT, 0777, 1 );
280  rtems_test_assert( n_sem1 != SEM_FAILED );
281
282  puts( "Init: sem_destroy - named sem1 - EINVAL" );
283  status = sem_destroy(n_sem1);
284  fatal_posix_service_status( status, -1, "sem_destroy named semaphore");
285  fatal_posix_service_status( errno, EINVAL,  "sem_destroy named semaphore");
286
287  puts( "Init: sem_open - Create an Existing sem (EEXIST)" );
288  n_sem2 = sem_open("sem1", O_CREAT | O_EXCL, 0777, 1);
289  fatal_posix_sem( n_sem2, "sem_open error return status" );
290  fatal_posix_service_status( errno, EEXIST,  "sem_open errno EEXIST");
291
292  puts( "Init: sem_open - Open new sem without create flag (ENOENT)" );
293  n_sem2 = sem_open("sem3", O_EXCL, 0777, 1);
294  fatal_posix_sem( n_sem2, "sem_open error return status" );
295  fatal_posix_service_status( errno, ENOENT,  "sem_open errno EEXIST");
296
297  /*
298   * XXX - Could not hit the following errors:
299   *   E_POSIX_Semaphore_Create_support only fails if
300   *     ENOSYS - When semaphore is shared between processes.
301   *     ENOSPC - When out of memory.
302   */
303
304  /*
305   * Validate we can wait on a semaphore opened with sem_open.
306   */
307
308  puts( "Init: sem_wait on sem1" );
309  status = sem_wait(n_sem1);
310  fatal_posix_service_status( status, 0, "sem_wait opened semaphore");
311
312  /*
313   * Validate a second open returns the same semaphore.
314   */
315
316  puts( "Init: sem_open - Open an existing sem ( same id )" );
317  n_sem2 = sem_open("sem1", 0 );
318  rtems_test_assert( n_sem2 == n_sem1 );
319
320  /*
321   * Unlink the semaphore, then verify an open of the same name produces a
322   * different semaphore.
323   */
324
325  puts( "Init: sem_unlink - sem1 SUCCESSFUL" );
326  status = sem_unlink( "sem1" );
327  fatal_posix_service_status( status, 0, "sem_unlink locked semaphore");
328
329  puts( "Init: sem_open - Reopen sem1 SUCCESSFUL with a different id" );
330  n_sem2 = sem_open( "sem1", O_CREAT | O_EXCL, 0777, 1);
331  rtems_test_assert( n_sem2 != SEM_FAILED );
332  rtems_test_assert( n_sem2 != n_sem1 );
333
334  /*
335   * Validate we can call close on a semaphore opened with sem_open.
336   */
337
338  puts( "Init: sem_close (1) - SUCCESSFUL" );
339  status = sem_close( n_sem1 );
340  fatal_posix_service_status( status, 0, "sem_close semaphore");
341
342  /*
343   * Validate it n_sem2 (the last open for sem1 name can be
344   * correctly closed and unlinked.
345   */
346
347  puts( "Init: sem_close (2) - SUCCESSFUL" );
348  status = sem_close( n_sem2 );
349  fatal_posix_service_status( status, 0, "sem_close semaphore");
350
351  puts( "Init: sem_unlink - sem1 (2) SUCCESSFUL" );
352  status = sem_unlink( "sem1" );
353  fatal_posix_service_status( status, 0, "sem_unlink locked semaphore");
354
355  puts( "Init: sem_close - UNSUCCESSFUL (EINVAL)" );
356  status = sem_close(n_sem2);
357  fatal_posix_service_status( status, -1, "sem_close error return status");
358  fatal_posix_service_status( errno, EINVAL, "sem_close errno EINVAL");
359
360  puts( "Init: sem_unlink - UNSUCCESSFUL (ENOENT)" );
361  status = sem_unlink("sem1");
362  fatal_posix_service_status( status, -1, "sem_unlink error return status");
363  fatal_posix_service_status( errno, ENOENT, "sem_close errno EINVAL");
364
365
366  /*
367   * Validate we can unlink (2)
368   */
369
370  puts( "Init: sem_unlink (NULL) - EINVAL" );
371  status = sem_unlink( NULL );
372  fatal_posix_service_status( status, -1, "sem_unlink error return status");
373  fatal_posix_service_status( errno, EINVAL, "sem_unlink errno value");
374
375  puts( "Init: sem_unlink (\"\") - ENOENT" );
376  status = sem_unlink( "" );
377  fatal_posix_service_status( status, -1, "sem_unlink error return status");
378  fatal_posix_service_status( errno, ENOENT, "sem_unlink errno value");
379
380  /*
381   * XXX - Cant' create location OBJECTS_ERROR or OBJECTS_REMOTE.
382   *       sem_close and sem_unlink.
383   */
384
385  puts( "Init: sem_unlink - UNSUCCESSFUL (ENOENT)" );
386  status = sem_unlink("sem2");
387  fatal_posix_service_status( status, -1, "sem_unlink error return status");
388  fatal_posix_service_status( errno, ENOENT, "sem_unlink errno ENOENT");
389  rtems_test_assert( (status == -1) && (errno == ENOENT) );
390
391  test_sem_wait_during_delete();
392  test_sem_post_overflow();
393  test_sem_init_too_large_inital_value();
394
395  /* Try adding in unlinking before closing... (can we still open?) */
396
397  TEST_END();
398  rtems_test_exit(0);
399
400  return NULL; /* just so the compiler thinks we returned something */
401}
402
403/* configuration information */
404#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
405#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
406
407#define CONFIGURE_POSIX_INIT_THREAD_TABLE
408
409#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
410
411#define CONFIGURE_MAXIMUM_POSIX_THREADS     2
412#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES  MAX_SEMS
413
414#define CONFIGURE_POSIX_INIT_THREAD_TABLE
415#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE \
416        (RTEMS_MINIMUM_STACK_SIZE * 4)
417
418#define CONFIGURE_INIT
419#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.