Created
August 20, 2021 13:55
-
-
Save joycemaferko/cd6877c6592d12f9bd4169ff3a6ede57 to your computer and use it in GitHub Desktop.
pthread_mutex_clocklock Test (psx18)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2021 Matthew Joyce | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
* POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
/* Defined to have access to function prototype in pthread.h */ | |
#define _GNU_SOURCE | |
#ifdef HAVE_CONFIG_H | |
#include "config.h" | |
#endif | |
#include <sched.h> | |
#define CONFIGURE_INIT | |
#include "system.h" | |
#include <errno.h> | |
#include <limits.h> | |
#include <stdio.h> | |
#include <rtems/score/todimpl.h> | |
#define NOT_ENOUGH_SECONDS 4 | |
#define ENOUGH_SECONDS 6 | |
pthread_t t1; | |
struct timespec to; | |
struct timespec abstime; | |
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; | |
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; | |
/* | |
* Further testing required. Call to mutex_lock or mutex_clocklock with | |
* Uninitialized global mutex object returns 0. Same call with unitialized | |
* mutex object declared in function scope returns EINVAL. | |
*/ | |
//pthread_mutex_t bad_mutex2; | |
clockid_t clock_id1 = CLOCK_MONOTONIC; | |
clockid_t clock_id2 = CLOCK_REALTIME; | |
clockid_t clock_id3 = CLOCK_MONOTONIC_RAW; | |
int eno; | |
int count; | |
int status; | |
const char rtems_test_name[] = "PSX 18"; | |
static void test_mutex_auto_initialization( void ) | |
{ | |
/* Expected pass: Standard lock without timeout */ | |
{ | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
eno = pthread_mutex_lock( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
eno = pthread_mutex_unlock( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
eno = pthread_mutex_destroy( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
} | |
/* Expected pass: CLOCK_MONOTONIC */ | |
{ | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
to.tv_sec = 0; | |
to.tv_nsec = 1; | |
eno = pthread_mutex_clocklock( &mutex, clock_id1, &to ); | |
rtems_test_assert( eno == 0 ); | |
eno = pthread_mutex_unlock( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
eno = pthread_mutex_destroy( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
} | |
/* Expected pass: CLOCK_REALTIME */ | |
{ | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
eno = clock_gettime( clock_id2, &to ); | |
rtems_test_assert( eno == 0 ); | |
to.tv_sec += 0; | |
to.tv_nsec += 1; | |
eno = pthread_mutex_clocklock( &mutex, clock_id2, &to ); | |
rtems_test_assert( eno == 0 ); | |
eno = pthread_mutex_unlock( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
eno = pthread_mutex_destroy( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
} | |
/* Expected fail: Unsupported clock */ | |
{ | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
to.tv_sec = 2; | |
to.tv_nsec = 1; | |
eno = pthread_mutex_clocklock( &mutex, clock_id3, &to ); | |
rtems_test_assert( eno == EINVAL ); | |
eno = pthread_mutex_destroy( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
} | |
/* Expected fail: Try to acquire lock already held in the same thread. */ | |
{ | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
pthread_mutex_lock( &mutex ); | |
eno = clock_gettime( clock_id2, &to ); | |
rtems_test_assert( eno == 0 ); | |
to.tv_sec += 10; | |
eno = pthread_mutex_clocklock( &mutex, clock_id2, &to); | |
rtems_test_assert( eno != 0 ); | |
eno = pthread_mutex_unlock( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
eno = pthread_mutex_destroy( &mutex ); | |
rtems_test_assert( eno == 0 ); | |
} | |
} | |
void *POSIX_Init( | |
void *argument | |
) | |
{ | |
TEST_BEGIN(); | |
test_mutex_auto_initialization(); | |
/* Expected fail: Insufficient time to acquire lock */ | |
printf( "1st iteration Begin (Clock Monotonic)\n" ); | |
status = pthread_mutex_lock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
status = pthread_create( &t1, NULL, thread_func_monotonic_fail, NULL ); | |
rtems_test_assert( status == 0 ); | |
/* Arbitrary sleep to test mutex_clocklock. */ | |
sleep(5); | |
while ( count == 0 ){ | |
eno = pthread_cond_wait( &cond, &mutex2 ); | |
if ( eno != 0 ) { | |
break; | |
} | |
} | |
count -= 1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
rtems_test_assert( eno == 0 ); | |
status = pthread_join( t1, NULL ); | |
rtems_test_assert( status == 0 ); | |
printf( "1st iteration END\n" ); | |
empty_line(); | |
/* Expected pass: Sufficient time to acquire lock */ | |
printf(" 2nd iteration Begin (Clock Monotonic)\n" ); | |
status = pthread_mutex_lock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
status = pthread_create( &t1, NULL, thread_func_monotonic_pass, NULL ); | |
rtems_test_assert( status == 0 ); | |
/* Arbitrary sleep to test mutex_clocklock. */ | |
sleep(5); | |
while ( count == 0 ){ | |
eno = pthread_cond_wait( &cond, &mutex2 ); | |
if ( eno != 0 ) { | |
break; | |
} | |
} | |
count -= 1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
rtems_test_assert( eno == 0 ); | |
status = pthread_join( t1, NULL ); | |
rtems_test_assert( status == 0 ); | |
printf( "2nd iteration END\n" ); | |
empty_line(); | |
/* Expected fail: Insufficient time to acquire lock */ | |
printf( "3rd iteration Begin (Clock Realtime)\n" ); | |
status = pthread_mutex_lock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
status = pthread_create( &t1, NULL, thread_func_realtime_fail, NULL ); | |
rtems_test_assert( status == 0 ); | |
/* Arbitrary sleep to test mutex_clocklock. */ | |
sleep(5); | |
while ( count == 0 ){ | |
eno = pthread_cond_wait( &cond, &mutex2 ); | |
if ( eno != 0 ) { | |
break; | |
} | |
} | |
count -= 1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
rtems_test_assert( eno == 0 ); | |
status = pthread_join( t1, NULL ); | |
rtems_test_assert( status == 0 ); | |
printf( "3rd iteration END\n" ); | |
empty_line(); | |
/* Expected pass: Sufficient time to acquire lock */ | |
printf( "4th iteration Begin (Clock Realtime)\n" ); | |
status = pthread_mutex_lock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
status = pthread_create( &t1, NULL, thread_func_realtime_pass, NULL ); | |
rtems_test_assert( status == 0 ); | |
/* Arbitrary sleep to test mutex_clocklock. */ | |
sleep(5); | |
while ( count == 0 ){ | |
eno = pthread_cond_wait( &cond, &mutex2 ); | |
if ( eno != 0 ) { | |
break; | |
} | |
} | |
count -= 1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
rtems_test_assert( eno == 0 ); | |
status = pthread_join( t1, NULL ); | |
rtems_test_assert( status == 0 ); | |
printf( "4th iteration END\n" ); | |
empty_line(); | |
/* Expected fail: unsupported clock */ | |
printf( "5th iteration Begin (Unsupported Clock)\n" ); | |
status = pthread_mutex_lock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
status = pthread_create( &t1, NULL, thread_func_bad_clock, NULL ); | |
rtems_test_assert( status == 0 ); | |
/* Arbitrary sleep to test mutex_clocklock. */ | |
sleep(5); | |
while ( count == 0 ){ | |
eno = pthread_cond_wait( &cond, &mutex2 ); | |
if ( eno != 0 ) { | |
break; | |
} | |
} | |
count -= 1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
rtems_test_assert( eno == 0 ); | |
status = pthread_join( t1, NULL ); | |
rtems_test_assert( status == 0 ); | |
printf( "5th iteration END\n" ); | |
empty_line(); | |
/* Expected fail: Invalid Abstime */ | |
printf( "6th iteration Begin (Invalid Abstime)\n" ); | |
status = pthread_mutex_lock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
status = pthread_create( &t1, NULL, thread_func_bad_time, NULL ); | |
rtems_test_assert( status == 0 ); | |
/* Arbitrary sleep to test mutex_clocklock. */ | |
sleep(5); | |
while ( count == 0 ){ | |
eno = pthread_cond_wait( &cond, &mutex2 ); | |
if ( eno != 0 ) { | |
break; | |
} | |
} | |
count -= 1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
rtems_test_assert( eno == 0 ); | |
status = pthread_join( t1, NULL ); | |
rtems_test_assert( status == 0 ); | |
printf( "6th iteration END\n" ); | |
empty_line(); | |
/* Expected fail: Invalid Mutex */ | |
/* | |
* Potential bug: pthread_mutex_lock should have undefined behavior when | |
* passing an uninitialized mutex. Currently it returns success. | |
*/ | |
printf( "7th iteration Begin (Invalid Mutex)\n" ); | |
pthread_mutex_t bad_mutex2; | |
status = pthread_mutex_lock( &bad_mutex2 ); | |
rtems_test_assert( status == EINVAL ); | |
status = pthread_create( &t1, NULL, thread_func_monotonic_bad_mutex, NULL ); | |
rtems_test_assert( status == 0 ); | |
/* Arbitrary sleep to test mutex_clocklock. */ | |
sleep(5); | |
while ( count == 0 ){ | |
eno = pthread_cond_wait( &cond, &bad_mutex2 ); | |
if ( eno != 0 ) { | |
break; | |
} | |
} | |
count -= 1; | |
status = pthread_mutex_unlock( &bad_mutex2 ); | |
rtems_test_assert( status == EINVAL ); | |
rtems_test_assert( eno == 0 ); | |
status = pthread_join( t1, NULL ); | |
rtems_test_assert( status == 0 ); | |
printf( "7th iteration END\n" ); | |
empty_line(); | |
TEST_END(); | |
rtems_test_exit( 0 ); | |
return NULL; | |
} | |
void *thread_func_monotonic_fail( void *arg ) | |
{ | |
int status; | |
status = clock_gettime( clock_id1, &abstime ); | |
rtems_test_assert( status == 0 ); | |
abstime.tv_sec += NOT_ENOUGH_SECONDS; | |
status = pthread_mutex_clocklock( &mutex2, clock_id1, &abstime ); | |
rtems_test_assert( status == ETIMEDOUT ); | |
printf("Return value of mutex_clocklock in thread_func is %d\n", status); | |
if ( count == 0 ) { | |
status = pthread_cond_signal( &cond ); | |
rtems_test_assert( status == 0 ); | |
} | |
count +=1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == EPERM ); | |
return NULL; | |
} | |
void *thread_func_monotonic_pass( void *arg ) | |
{ | |
int status; | |
status = clock_gettime( clock_id1, &abstime ); | |
rtems_test_assert( status == 0 ); | |
abstime.tv_sec += ENOUGH_SECONDS; | |
status = pthread_mutex_clocklock( &mutex2, clock_id1, &abstime ); | |
rtems_test_assert( status == 0 ); | |
printf("Return value of mutex_clocklock in thread_func is %d\n", status); | |
if ( count == 0 ) { | |
status = pthread_cond_signal( &cond ); | |
rtems_test_assert( status == 0 ); | |
} | |
count +=1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
return NULL; | |
} | |
void *thread_func_realtime_fail( void *arg ) | |
{ | |
int status; | |
status = clock_gettime( clock_id2, &abstime ); | |
rtems_test_assert( status == 0 ); | |
abstime.tv_sec += NOT_ENOUGH_SECONDS; | |
status = pthread_mutex_clocklock( &mutex2, clock_id2, &abstime ); | |
rtems_test_assert( status == ETIMEDOUT ); | |
printf("Return value of mutex_clocklock in thread_func is %d\n", status); | |
if ( count == 0 ) { | |
status = pthread_cond_signal( &cond ); | |
rtems_test_assert( status == 0 ); | |
} | |
count +=1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == EPERM ); | |
return NULL; | |
} | |
void *thread_func_realtime_pass( void *arg ) | |
{ | |
int status; | |
status = clock_gettime( clock_id2, &abstime ); | |
rtems_test_assert( status == 0 ); | |
abstime.tv_sec += ENOUGH_SECONDS; | |
status = pthread_mutex_clocklock( &mutex2, clock_id2, &abstime ); | |
rtems_test_assert( status == 0 ); | |
printf("Return value of mutex_clocklock in thread_func is %d\n", status); | |
if ( count == 0 ) { | |
status = pthread_cond_signal( &cond ); | |
rtems_test_assert( status == 0 ); | |
} | |
count +=1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == 0 ); | |
return NULL; | |
} | |
void *thread_func_bad_clock( void *arg ) | |
{ | |
int status; | |
status = pthread_mutex_clocklock( &mutex2, clock_id3, &abstime ); | |
rtems_test_assert( status == EINVAL ); | |
printf("Return value of mutex_clocklock in thread_func is %d\n", status); | |
if ( count == 0 ) { | |
status = pthread_cond_signal( &cond ); | |
rtems_test_assert( status == 0 ); | |
} | |
count +=1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == EPERM ); | |
return NULL; | |
} | |
void *thread_func_bad_time( void *arg ) | |
{ | |
int status; | |
status = pthread_mutex_clocklock( &mutex2, clock_id3, NULL ); | |
rtems_test_assert( status == EINVAL ); | |
printf("Return value of mutex_clocklock in thread_func is %d\n", status); | |
if ( count == 0 ) { | |
status = pthread_cond_signal( &cond ); | |
rtems_test_assert( status == 0 ); | |
} | |
count +=1; | |
status = pthread_mutex_unlock( &mutex2 ); | |
rtems_test_assert( status == EPERM ); | |
return NULL; | |
} | |
void *thread_func_monotonic_bad_mutex( void *arg ) | |
{ | |
int status; | |
pthread_mutex_t bad_mutex2; | |
status = clock_gettime( clock_id1, &abstime ); | |
rtems_test_assert( status == 0 ); | |
abstime.tv_sec += ENOUGH_SECONDS; | |
status = pthread_mutex_clocklock( &bad_mutex2, clock_id1, &abstime ); | |
rtems_test_assert( status == EINVAL ); | |
printf("Return value of mutex_clocklock in thread_func is %d\n", status); | |
if ( count == 0 ) { | |
status = pthread_cond_signal( &cond ); | |
rtems_test_assert( status == 0 ); | |
} | |
count +=1; | |
status = pthread_mutex_unlock( &bad_mutex2 ); | |
rtems_test_assert( status == EINVAL ); | |
return NULL; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* system.h | |
* | |
* This include file contains information that is included in every | |
* function in the test set. | |
* | |
* COPYRIGHT (c) 1989-1999. | |
* On-Line Applications Research Corporation (OAR). | |
* | |
* The license and distribution terms for this file may be | |
* found in the file LICENSE in this distribution or at | |
* http://www.rtems.org/license/LICENSE. | |
*/ | |
/* functions */ | |
#include <pmacros.h> | |
void *POSIX_Init( | |
void *argument | |
); | |
void *thread_func_monotonic_fail( | |
void *argument | |
); | |
void *thread_func_monotonic_pass( | |
void *argument | |
); | |
void *thread_func_realtime_fail( | |
void *argument | |
); | |
void *thread_func_realtime_pass( | |
void *argument | |
); | |
void *thread_func_bad_clock( | |
void *argument | |
); | |
void *thread_func_bad_time( | |
void *argument | |
); | |
void *thread_func_monotonic_bad_mutex( | |
void *argument | |
); | |
/* configuration information */ | |
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER | |
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER | |
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION | |
#define CONFIGURE_MAXIMUM_POSIX_THREADS 4 | |
#define CONFIGURE_POSIX_INIT_THREAD_TABLE | |
#include <rtems/confdefs.h> | |
/* end of include file */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment