1570af302Sopenharmony_ci// sem_wait and sem_timedwait are cancellation points 2570af302Sopenharmony_ci#include <pthread.h> 3570af302Sopenharmony_ci#include <semaphore.h> 4570af302Sopenharmony_ci#include <string.h> 5570af302Sopenharmony_ci#include "test.h" 6570af302Sopenharmony_ci 7570af302Sopenharmony_ci#define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) ) 8570af302Sopenharmony_ci#define TESTR(r, f, m) ( \ 9570af302Sopenharmony_ci ((r) = (f)) == 0 || (t_error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) ) 10570af302Sopenharmony_ci 11570af302Sopenharmony_ciextern int __sem_timedwait_time64(sem_t *__restrict, const struct timespec *__restrict); 12570af302Sopenharmony_ci 13570af302Sopenharmony_cistatic sem_t sem1, sem2; 14570af302Sopenharmony_ci 15570af302Sopenharmony_cistatic int seqno; 16570af302Sopenharmony_ci 17570af302Sopenharmony_cistatic void wait_cancel(void *arg) 18570af302Sopenharmony_ci{ 19570af302Sopenharmony_ci pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); 20570af302Sopenharmony_ci while (sem_wait(&sem1)); 21570af302Sopenharmony_ci pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); 22570af302Sopenharmony_ci seqno = 1; 23570af302Sopenharmony_ci} 24570af302Sopenharmony_ci 25570af302Sopenharmony_cistatic void *start_sem_wait(void *arg) 26570af302Sopenharmony_ci{ 27570af302Sopenharmony_ci wait_cancel(arg); 28570af302Sopenharmony_ci sem_wait(&sem2); 29570af302Sopenharmony_ci seqno = 2; 30570af302Sopenharmony_ci return 0; 31570af302Sopenharmony_ci} 32570af302Sopenharmony_ci 33570af302Sopenharmony_cistatic void *start_sem_timedwait(void *arg) 34570af302Sopenharmony_ci{ 35570af302Sopenharmony_ci wait_cancel(arg); 36570af302Sopenharmony_ci sem_timedwait(&sem2, &(struct timespec){1, 0}); 37570af302Sopenharmony_ci seqno = 2; 38570af302Sopenharmony_ci return 0; 39570af302Sopenharmony_ci} 40570af302Sopenharmony_ci 41570af302Sopenharmony_cistatic void *start_sem_timedwait_time64(void *arg) 42570af302Sopenharmony_ci{ 43570af302Sopenharmony_ci wait_cancel(arg); 44570af302Sopenharmony_ci __sem_timedwait_time64(&sem2, &(struct timespec){1, 0}); 45570af302Sopenharmony_ci seqno = 2; 46570af302Sopenharmony_ci return 0; 47570af302Sopenharmony_ci} 48570af302Sopenharmony_ci 49570af302Sopenharmony_ciint main(void) 50570af302Sopenharmony_ci{ 51570af302Sopenharmony_ci pthread_t td; 52570af302Sopenharmony_ci int r; 53570af302Sopenharmony_ci void *res; 54570af302Sopenharmony_ci 55570af302Sopenharmony_ci TESTR(r, sem_init(&sem1, 0, 0), "creating semaphore"); 56570af302Sopenharmony_ci TESTR(r, sem_init(&sem2, 0, 1), "creating semaphore"); 57570af302Sopenharmony_ci 58570af302Sopenharmony_ci /* Cancellation on uncontended sem_wait */ 59570af302Sopenharmony_ci seqno = 0; 60570af302Sopenharmony_ci TESTR(r, pthread_create(&td, 0, start_sem_wait, 0), "failed to create thread"); 61570af302Sopenharmony_ci TESTR(r, pthread_cancel(td), "canceling"); 62570af302Sopenharmony_ci sem_post(&sem1); 63570af302Sopenharmony_ci TESTR(r, pthread_join(td, &res), "joining canceled thread after uncontended sem_wait"); 64570af302Sopenharmony_ci TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after uncontended sem_wait"); 65570af302Sopenharmony_ci TESTC(seqno == 1, "uncontended sem_wait"); 66570af302Sopenharmony_ci 67570af302Sopenharmony_ci /* Cancellation on blocking sem_wait */ 68570af302Sopenharmony_ci seqno = 0; 69570af302Sopenharmony_ci sem_trywait(&sem2); 70570af302Sopenharmony_ci TESTR(r, pthread_create(&td, 0, start_sem_wait, 0), "failed to create thread"); 71570af302Sopenharmony_ci TESTR(r, pthread_cancel(td), "canceling"); 72570af302Sopenharmony_ci sem_post(&sem1); 73570af302Sopenharmony_ci TESTR(r, pthread_join(td, &res), "joining canceled thread after blocking sem_wait"); 74570af302Sopenharmony_ci TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after blocking sem_wait"); 75570af302Sopenharmony_ci TESTC(seqno == 1, "blocking sem_wait"); 76570af302Sopenharmony_ci 77570af302Sopenharmony_ci /* Cancellation on uncontended sem_timedwait */ 78570af302Sopenharmony_ci seqno = 0; 79570af302Sopenharmony_ci sem_post(&sem2); 80570af302Sopenharmony_ci TESTR(r, pthread_create(&td, 0, start_sem_timedwait, 0), "failed to create thread"); 81570af302Sopenharmony_ci TESTR(r, pthread_cancel(td), "canceling"); 82570af302Sopenharmony_ci sem_post(&sem1); 83570af302Sopenharmony_ci TESTR(r, pthread_join(td, &res), "joining canceled thread after uncontended sem_timedwait"); 84570af302Sopenharmony_ci TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after uncontended sem_timedwait"); 85570af302Sopenharmony_ci TESTC(seqno == 1, "uncontended sem_timedwait"); 86570af302Sopenharmony_ci 87570af302Sopenharmony_ci /* Cancellation on blocking sem_timedwait */ 88570af302Sopenharmony_ci seqno = 0; 89570af302Sopenharmony_ci sem_trywait(&sem2); 90570af302Sopenharmony_ci TESTR(r, pthread_create(&td, 0, start_sem_timedwait, 0), "failed to create thread"); 91570af302Sopenharmony_ci TESTR(r, pthread_cancel(td), "canceling"); 92570af302Sopenharmony_ci sem_post(&sem1); 93570af302Sopenharmony_ci TESTR(r, pthread_join(td, &res), "joining canceled thread after blocking sem_timedwait"); 94570af302Sopenharmony_ci TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after blocking sem_timedwait"); 95570af302Sopenharmony_ci TESTC(seqno == 1, "blocking sem_timedwait"); 96570af302Sopenharmony_ci 97570af302Sopenharmony_ci /* Cancellation on blocking __sem_timedwait_time64 */ 98570af302Sopenharmony_ci seqno = 0; 99570af302Sopenharmony_ci sem_trywait(&sem2); 100570af302Sopenharmony_ci TESTR(r, pthread_create(&td, 0, start_sem_timedwait_time64, 0), "failed to create thread"); 101570af302Sopenharmony_ci TESTR(r, pthread_cancel(td), "canceling"); 102570af302Sopenharmony_ci sem_post(&sem1); 103570af302Sopenharmony_ci TESTR(r, pthread_join(td, &res), "joining canceled thread after blocking __sem_timedwait_time64"); 104570af302Sopenharmony_ci TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after blocking __sem_timedwait_time64"); 105570af302Sopenharmony_ci TESTC(seqno == 1, "blocking __sem_timedwait_time64"); 106570af302Sopenharmony_ci 107570af302Sopenharmony_ci return t_status; 108570af302Sopenharmony_ci} 109