run clang-format

This commit is contained in:
Bassem Girgis
2018-10-17 23:47:57 -05:00
parent 558e8e22da
commit c8a8949366
56 changed files with 4153 additions and 3900 deletions

View File

@@ -22,177 +22,183 @@
* been on the list.
*/
typedef struct alarm_tag {
struct alarm_tag *link;
int seconds;
time_t time; /* seconds from EPOCH */
char message[64];
struct alarm_tag* link;
int seconds;
time_t time; /* seconds from EPOCH */
char message[64];
} alarm_t;
pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t alarm_cond = PTHREAD_COND_INITIALIZER;
alarm_t *alarm_list = NULL;
time_t current_alarm = 0;
pthread_cond_t alarm_cond = PTHREAD_COND_INITIALIZER;
alarm_t* alarm_list = NULL;
time_t current_alarm = 0;
/*
* Insert alarm entry on list, in order.
*/
void alarm_insert (alarm_t *alarm)
void
alarm_insert(alarm_t* alarm)
{
int status;
alarm_t **last, *next;
int status;
alarm_t **last, *next;
/*
* LOCKING PROTOCOL:
*
* This routine requires that the caller have locked the
* alarm_mutex!
*/
last = &alarm_list;
next = *last;
while (next != NULL) {
if (next->time >= alarm->time) {
alarm->link = next;
*last = alarm;
break;
}
last = &next->link;
next = next->link;
}
/*
* If we reached the end of the list, insert the new alarm
* there. ("next" is NULL, and "last" points to the link
* field of the last item, or to the list header.)
*/
if (next == NULL) {
*last = alarm;
alarm->link = NULL;
/*
* LOCKING PROTOCOL:
*
* This routine requires that the caller have locked the
* alarm_mutex!
*/
last = &alarm_list;
next = *last;
while (next != NULL) {
if (next->time >= alarm->time) {
alarm->link = next;
*last = alarm;
break;
}
last = &next->link;
next = next->link;
}
/*
* If we reached the end of the list, insert the new alarm
* there. ("next" is NULL, and "last" points to the link
* field of the last item, or to the list header.)
*/
if (next == NULL) {
*last = alarm;
alarm->link = NULL;
}
#ifdef DEBUG
printf ("[list: ");
for (next = alarm_list; next != NULL; next = next->link)
printf ("%d(%d)[\"%s\"] ", next->time,
next->time - time (NULL), next->message);
printf ("]\n");
printf("[list: ");
for (next = alarm_list; next != NULL; next = next->link)
printf(
"%d(%d)[\"%s\"] ", next->time, next->time - time(NULL), next->message);
printf("]\n");
#endif
/*
* Wake the alarm thread if it is not busy (that is, if
* current_alarm is 0, signifying that it's waiting for
* work), or if the new alarm comes before the one on
* which the alarm thread is waiting.
*/
if (current_alarm == 0 || alarm->time < current_alarm) {
current_alarm = alarm->time;
status = pthread_cond_signal (&alarm_cond);
if (status != 0)
err_abort (status, "Signal cond");
}
/*
* Wake the alarm thread if it is not busy (that is, if
* current_alarm is 0, signifying that it's waiting for
* work), or if the new alarm comes before the one on
* which the alarm thread is waiting.
*/
if (current_alarm == 0 || alarm->time < current_alarm) {
current_alarm = alarm->time;
status = pthread_cond_signal(&alarm_cond);
if (status != 0)
err_abort(status, "Signal cond");
}
}
/*
* The alarm thread's start routine.
*/
void *alarm_thread (void *arg)
void*
alarm_thread(void* arg)
{
alarm_t *alarm;
struct timespec cond_time;
time_t now;
int status, expired;
alarm_t* alarm;
struct timespec cond_time;
time_t now;
int status, expired;
/*
* Loop forever, processing commands. The alarm thread will
* be disintegrated when the process exits. Lock the mutex
* at the start -- it will be unlocked during condition
* waits, so the main thread can insert alarms.
*/
status = pthread_mutex_lock(&alarm_mutex);
if (status != 0)
err_abort(status, "Lock mutex");
while (1) {
/*
* If the alarm list is empty, wait until an alarm is
* added. Setting current_alarm to 0 informs the insert
* routine that the thread is not busy.
*/
current_alarm = 0;
while (alarm_list == NULL) {
status = pthread_cond_wait(&alarm_cond, &alarm_mutex);
if (status != 0)
err_abort(status, "Wait on cond");
}
alarm = alarm_list;
alarm_list = alarm->link;
now = time(NULL);
expired = 0;
if (alarm->time > now) {
#ifdef DEBUG
printf("[waiting: %d(%d)\"%s\"]\n",
alarm->time,
alarm->time - time(NULL),
alarm->message);
#endif
cond_time.tv_sec = alarm->time;
cond_time.tv_nsec = 0;
current_alarm = alarm->time;
while (current_alarm == alarm->time) {
status = pthread_cond_timedwait(&alarm_cond, &alarm_mutex, &cond_time);
if (status == ETIMEDOUT) {
expired = 1;
break;
}
if (status != 0)
err_abort(status, "Cond timedwait");
}
if (!expired)
alarm_insert(alarm);
}
else
expired = 1;
if (expired) {
printf("(%d) %s\n", alarm->seconds, alarm->message);
free(alarm);
}
}
}
int
main(int argc, char* argv[])
{
int status;
char line[128];
alarm_t* alarm;
pthread_t thread;
status = pthread_create(&thread, NULL, alarm_thread, NULL);
if (status != 0)
err_abort(status, "Create alarm thread");
while (1) {
printf("Alarm> ");
if (fgets(line, sizeof(line), stdin) == NULL)
exit(0);
if (strlen(line) <= 1)
continue;
alarm = (alarm_t*) malloc(sizeof(alarm_t));
if (alarm == NULL)
errno_abort("Allocate alarm");
/*
* Loop forever, processing commands. The alarm thread will
* be disintegrated when the process exits. Lock the mutex
* at the start -- it will be unlocked during condition
* waits, so the main thread can insert alarms.
* Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace.
*/
status = pthread_mutex_lock (&alarm_mutex);
if (status != 0)
err_abort (status, "Lock mutex");
while (1) {
/*
* If the alarm list is empty, wait until an alarm is
* added. Setting current_alarm to 0 informs the insert
* routine that the thread is not busy.
*/
current_alarm = 0;
while (alarm_list == NULL) {
status = pthread_cond_wait (&alarm_cond, &alarm_mutex);
if (status != 0)
err_abort (status, "Wait on cond");
}
alarm = alarm_list;
alarm_list = alarm->link;
now = time (NULL);
expired = 0;
if (alarm->time > now) {
#ifdef DEBUG
printf ("[waiting: %d(%d)\"%s\"]\n", alarm->time,
alarm->time - time (NULL), alarm->message);
#endif
cond_time.tv_sec = alarm->time;
cond_time.tv_nsec = 0;
current_alarm = alarm->time;
while (current_alarm == alarm->time) {
status = pthread_cond_timedwait (
&alarm_cond, &alarm_mutex, &cond_time);
if (status == ETIMEDOUT) {
expired = 1;
break;
}
if (status != 0)
err_abort (status, "Cond timedwait");
}
if (!expired)
alarm_insert (alarm);
} else
expired = 1;
if (expired) {
printf ("(%d) %s\n", alarm->seconds, alarm->message);
free (alarm);
}
if (sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message) < 2) {
fprintf(stderr, "Bad command\n");
free(alarm);
}
}
int main (int argc, char *argv[])
{
int status;
char line[128];
alarm_t *alarm;
pthread_t thread;
status = pthread_create (
&thread, NULL, alarm_thread, NULL);
if (status != 0)
err_abort (status, "Create alarm thread");
while (1) {
printf ("Alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
if (strlen (line) <= 1) continue;
alarm = (alarm_t*)malloc (sizeof (alarm_t));
if (alarm == NULL)
errno_abort ("Allocate alarm");
/*
* Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace.
*/
if (sscanf (line, "%d %64[^\n]",
&alarm->seconds, alarm->message) < 2) {
fprintf (stderr, "Bad command\n");
free (alarm);
} else {
status = pthread_mutex_lock (&alarm_mutex);
if (status != 0)
err_abort (status, "Lock mutex");
alarm->time = time (NULL) + alarm->seconds;
/*
* Insert the new alarm into the list of alarms,
* sorted by expiration time.
*/
alarm_insert (alarm);
status = pthread_mutex_unlock (&alarm_mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
}
else {
status = pthread_mutex_lock(&alarm_mutex);
if (status != 0)
err_abort(status, "Lock mutex");
alarm->time = time(NULL) + alarm->seconds;
/*
* Insert the new alarm into the list of alarms,
* sorted by expiration time.
*/
alarm_insert(alarm);
status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0)
err_abort(status, "Unlock mutex");
}
}
}

View File

@@ -22,154 +22,159 @@
* been on the list.
*/
typedef struct alarm_tag {
struct alarm_tag *link;
int seconds;
time_t time; /* seconds from EPOCH */
char message[64];
struct alarm_tag* link;
int seconds;
time_t time; /* seconds from EPOCH */
char message[64];
} alarm_t;
pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;
alarm_t *alarm_list = NULL;
alarm_t* alarm_list = NULL;
/*
* The alarm thread's start routine.
*/
void *alarm_thread (void *arg)
void*
alarm_thread(void* arg)
{
alarm_t *alarm;
int sleep_time;
time_t now;
int status;
alarm_t* alarm;
int sleep_time;
time_t now;
int status;
/*
* Loop forever, processing commands. The alarm thread will
* be disintegrated when the process exits.
*/
while (1) {
status = pthread_mutex_lock(&alarm_mutex);
if (status != 0)
err_abort(status, "Lock mutex");
alarm = alarm_list;
/*
* Loop forever, processing commands. The alarm thread will
* be disintegrated when the process exits.
* If the alarm list is empty, wait for one second. This
* allows the main thread to run, and read another
* command. If the list is not empty, remove the first
* item. Compute the number of seconds to wait -- if the
* result is less than 0 (the time has passed), then set
* the sleep_time to 0.
*/
while (1) {
status = pthread_mutex_lock (&alarm_mutex);
if (status != 0)
err_abort (status, "Lock mutex");
alarm = alarm_list;
/*
* If the alarm list is empty, wait for one second. This
* allows the main thread to run, and read another
* command. If the list is not empty, remove the first
* item. Compute the number of seconds to wait -- if the
* result is less than 0 (the time has passed), then set
* the sleep_time to 0.
*/
if (alarm == NULL)
sleep_time = 1;
else {
alarm_list = alarm->link;
now = time (NULL);
if (alarm->time <= now)
sleep_time = 0;
else
sleep_time = alarm->time - now;
if (alarm == NULL)
sleep_time = 1;
else {
alarm_list = alarm->link;
now = time(NULL);
if (alarm->time <= now)
sleep_time = 0;
else
sleep_time = alarm->time - now;
#ifdef DEBUG
printf ("[waiting: %d(%d)\"%s\"]\n", alarm->time,
sleep_time, alarm->message);
printf(
"[waiting: %d(%d)\"%s\"]\n", alarm->time, sleep_time, alarm->message);
#endif
}
/*
* Unlock the mutex before waiting, so that the main
* thread can lock it to insert a new alarm request. If
* the sleep_time is 0, then call sched_yield, giving
* the main thread a chance to run if it has been
* readied by user input, without delaying the message
* if there's no input.
*/
status = pthread_mutex_unlock (&alarm_mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
if (sleep_time > 0)
sleep (sleep_time);
else
sched_yield ();
/*
* If a timer expired, print the message and free the
* structure.
*/
if (alarm != NULL) {
printf ("(%d) %s\n", alarm->seconds, alarm->message);
free (alarm);
}
}
}
int main (int argc, char *argv[])
{
int status;
char line[128];
alarm_t *alarm, **last, *next;
pthread_t thread;
status = pthread_create (
&thread, NULL, alarm_thread, NULL);
/*
* Unlock the mutex before waiting, so that the main
* thread can lock it to insert a new alarm request. If
* the sleep_time is 0, then call sched_yield, giving
* the main thread a chance to run if it has been
* readied by user input, without delaying the message
* if there's no input.
*/
status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0)
err_abort (status, "Create alarm thread");
while (1) {
printf ("alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
if (strlen (line) <= 1) continue;
alarm = (alarm_t*)malloc (sizeof (alarm_t));
if (alarm == NULL)
errno_abort ("Allocate alarm");
err_abort(status, "Unlock mutex");
if (sleep_time > 0)
sleep(sleep_time);
else
sched_yield();
/*
* Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace.
*/
if (sscanf (line, "%d %64[^\n]",
&alarm->seconds, alarm->message) < 2) {
fprintf (stderr, "Bad command\n");
free (alarm);
} else {
status = pthread_mutex_lock (&alarm_mutex);
if (status != 0)
err_abort (status, "Lock mutex");
alarm->time = time (NULL) + alarm->seconds;
/*
* Insert the new alarm into the list of alarms,
* sorted by expiration time.
*/
last = &alarm_list;
next = *last;
while (next != NULL) {
if (next->time >= alarm->time) {
alarm->link = next;
*last = alarm;
break;
}
last = &next->link;
next = next->link;
}
/*
* If we reached the end of the list, insert the new
* alarm there. ("next" is NULL, and "last" points
* to the link field of the last item, or to the
* list header).
*/
if (next == NULL) {
*last = alarm;
alarm->link = NULL;
}
#ifdef DEBUG
printf ("[list: ");
for (next = alarm_list; next != NULL; next = next->link)
printf ("%d(%d)[\"%s\"] ", next->time,
next->time - time (NULL), next->message);
printf ("]\n");
#endif
status = pthread_mutex_unlock (&alarm_mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
}
/*
* If a timer expired, print the message and free the
* structure.
*/
if (alarm != NULL) {
printf("(%d) %s\n", alarm->seconds, alarm->message);
free(alarm);
}
}
}
int
main(int argc, char* argv[])
{
int status;
char line[128];
alarm_t *alarm, **last, *next;
pthread_t thread;
status = pthread_create(&thread, NULL, alarm_thread, NULL);
if (status != 0)
err_abort(status, "Create alarm thread");
while (1) {
printf("alarm> ");
if (fgets(line, sizeof(line), stdin) == NULL)
exit(0);
if (strlen(line) <= 1)
continue;
alarm = (alarm_t*) malloc(sizeof(alarm_t));
if (alarm == NULL)
errno_abort("Allocate alarm");
/*
* Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace.
*/
if (sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message) < 2) {
fprintf(stderr, "Bad command\n");
free(alarm);
}
else {
status = pthread_mutex_lock(&alarm_mutex);
if (status != 0)
err_abort(status, "Lock mutex");
alarm->time = time(NULL) + alarm->seconds;
/*
* Insert the new alarm into the list of alarms,
* sorted by expiration time.
*/
last = &alarm_list;
next = *last;
while (next != NULL) {
if (next->time >= alarm->time) {
alarm->link = next;
*last = alarm;
break;
}
last = &next->link;
next = next->link;
}
/*
* If we reached the end of the list, insert the new
* alarm there. ("next" is NULL, and "last" points
* to the link field of the last item, or to the
* list header).
*/
if (next == NULL) {
*last = alarm;
alarm->link = NULL;
}
#ifdef DEBUG
printf("[list: ");
for (next = alarm_list; next != NULL; next = next->link)
printf("%d(%d)[\"%s\"] ",
next->time,
next->time - time(NULL),
next->message);
printf("]\n");
#endif
status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0)
err_abort(status, "Unlock mutex");
}
}
}

View File

@@ -39,7 +39,9 @@ std::list<alarm_t> alarm_list;
/*
* The alarm thread's start routine.
*/
void *alarm_thread(void *arg) {
void*
alarm_thread(void* arg)
{
int sleep_time;
time_t now;
int status;
@@ -50,16 +52,18 @@ void *alarm_thread(void *arg) {
*/
while (1) {
status = pthread_mutex_lock(&alarm_mutex);
if (status != 0) err_abort(status, "Lock mutex");
if (status != 0)
err_abort(status, "Lock mutex");
now = time(NULL);
now = time(NULL);
sleep_time = 0;
for (auto it = alarm_list.begin(); it != alarm_list.end();) {
if (it->time <= now) {
printf("(%d) %s\n", it->seconds, it->message);
it = alarm_list.erase(it);
} else {
}
else {
sleep_time = MIN(it->time - now, sleep_time);
++it;
}
@@ -74,7 +78,8 @@ void *alarm_thread(void *arg) {
* if there's no input.
*/
status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0) err_abort(status, "Unlock mutex");
if (status != 0)
err_abort(status, "Unlock mutex");
if (sleep_time > 0)
sleep(sleep_time);
else
@@ -82,17 +87,22 @@ void *alarm_thread(void *arg) {
}
}
int main(int argc, char *argv[]) {
int
main(int argc, char* argv[])
{
int status;
char line[128];
pthread_t thread;
status = pthread_create(&thread, NULL, alarm_thread, NULL);
if (status != 0) err_abort(status, "Create alarm thread");
if (status != 0)
err_abort(status, "Create alarm thread");
while (1) {
printf("alarm> ");
if (fgets(line, sizeof(line), stdin) == NULL) exit(0);
if (strlen(line) <= 1) continue;
if (fgets(line, sizeof(line), stdin) == NULL)
exit(0);
if (strlen(line) <= 1)
continue;
alarm_t alarm;
/*
@@ -102,11 +112,13 @@ int main(int argc, char *argv[]) {
*/
if (sscanf(line, "%d %64[^\n]", &alarm.seconds, alarm.message) < 2) {
fprintf(stderr, "Bad command\n");
} else {
}
else {
alarm.time = time(NULL) + alarm.seconds;
status = pthread_mutex_lock(&alarm_mutex);
if (status != 0) err_abort(status, "Lock mutex");
if (status != 0)
err_abort(status, "Lock mutex");
/*
* Insert the new alarm into the list of alarms.
@@ -115,13 +127,16 @@ int main(int argc, char *argv[]) {
#ifdef DEBUG
printf("[list: ");
for (const auto &iAlarm : alarm_list)
printf("%d(%d)[\"%s\"] ", iAlarm.time, iAlarm.time - time(NULL),
for (const auto& iAlarm : alarm_list)
printf("%d(%d)[\"%s\"] ",
iAlarm.time,
iAlarm.time - time(NULL),
iAlarm.message);
printf("]\n");
#endif
status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0) err_abort(status, "Unlock mutex");
if (status != 0)
err_abort(status, "Unlock mutex");
}
}
}

View File

@@ -17,75 +17,73 @@
/*
* Initialize a static array of 3 mutexes.
*/
pthread_mutex_t mutex[3] = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER
};
pthread_mutex_t mutex[3] = {PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER};
int backoff = 1; /* Whether to backoff or deadlock */
int yield_flag = 0; /* 0: no yield, >0: yield, <0: sleep */
int backoff = 1; /* Whether to backoff or deadlock */
int yield_flag = 0; /* 0: no yield, >0: yield, <0: sleep */
/*
* This is a thread start routine that locks all mutexes in
* order, to ensure a conflict with lock_reverse, which does the
* opposite.
*/
void *lock_forward (void *arg)
void*
lock_forward(void* arg)
{
int i, iterate, backoffs;
int status;
int i, iterate, backoffs;
int status;
for (iterate = 0; iterate < ITERATIONS; iterate++) {
backoffs = 0;
for (i = 0; i < 3; i++) {
if (i == 0) {
status = pthread_mutex_lock (&mutex[i]);
if (status != 0)
err_abort (status, "First lock");
} else {
if (backoff)
status = pthread_mutex_trylock (&mutex[i]);
else
status = pthread_mutex_lock (&mutex[i]);
if (status == EBUSY) {
backoffs++;
DPRINTF ((
" [forward locker backing off at %d]\n",
i));
for (; i >= 0; i--) {
status = pthread_mutex_unlock (&mutex[i]);
if (status != 0)
err_abort (status, "Backoff");
}
} else {
if (status != 0)
err_abort (status, "Lock mutex");
DPRINTF ((" forward locker got %d\n", i));
}
}
/*
* Yield processor, if needed to be sure locks get
* interleaved on a uniprocessor.
*/
if (yield_flag) {
if (yield_flag > 0)
sched_yield ();
else
sleep (1);
}
for (iterate = 0; iterate < ITERATIONS; iterate++) {
backoffs = 0;
for (i = 0; i < 3; i++) {
if (i == 0) {
status = pthread_mutex_lock(&mutex[i]);
if (status != 0)
err_abort(status, "First lock");
}
else {
if (backoff)
status = pthread_mutex_trylock(&mutex[i]);
else
status = pthread_mutex_lock(&mutex[i]);
if (status == EBUSY) {
backoffs++;
DPRINTF((" [forward locker backing off at %d]\n", i));
for (; i >= 0; i--) {
status = pthread_mutex_unlock(&mutex[i]);
if (status != 0)
err_abort(status, "Backoff");
}
}
/*
* Report that we got 'em, and unlock to try again.
*/
printf (
"lock forward got all locks, %d backoffs\n", backoffs);
pthread_mutex_unlock (&mutex[2]);
pthread_mutex_unlock (&mutex[1]);
pthread_mutex_unlock (&mutex[0]);
sched_yield ();
else {
if (status != 0)
err_abort(status, "Lock mutex");
DPRINTF((" forward locker got %d\n", i));
}
}
/*
* Yield processor, if needed to be sure locks get
* interleaved on a uniprocessor.
*/
if (yield_flag) {
if (yield_flag > 0)
sched_yield();
else
sleep(1);
}
}
return NULL;
/*
* Report that we got 'em, and unlock to try again.
*/
printf("lock forward got all locks, %d backoffs\n", backoffs);
pthread_mutex_unlock(&mutex[2]);
pthread_mutex_unlock(&mutex[1]);
pthread_mutex_unlock(&mutex[0]);
sched_yield();
}
return NULL;
}
/*
@@ -93,107 +91,106 @@ void *lock_forward (void *arg)
* reverse order, to ensure a conflict with lock_forward, which
* does the opposite.
*/
void *lock_backward (void *arg)
void*
lock_backward(void* arg)
{
int i, iterate, backoffs;
int status;
int i, iterate, backoffs;
int status;
for (iterate = 0; iterate < ITERATIONS; iterate++) {
backoffs = 0;
for (i = 2; i >= 0; i--) {
if (i == 2) {
status = pthread_mutex_lock (&mutex[i]);
if (status != 0)
err_abort (status, "First lock");
} else {
if (backoff)
status = pthread_mutex_trylock (&mutex[i]);
else
status = pthread_mutex_lock (&mutex[i]);
if (status == EBUSY) {
backoffs++;
DPRINTF ((
" [backward locker backing off at %d]\n",
i));
for (; i < 3; i++) {
status = pthread_mutex_unlock (&mutex[i]);
if (status != 0)
err_abort (status, "Backoff");
}
} else {
if (status != 0)
err_abort (status, "Lock mutex");
DPRINTF ((" backward locker got %d\n", i));
}
}
/*
* Yield processor, if needed to be sure locks get
* interleaved on a uniprocessor.
*/
if (yield_flag) {
if (yield_flag > 0)
sched_yield ();
else
sleep (1);
}
for (iterate = 0; iterate < ITERATIONS; iterate++) {
backoffs = 0;
for (i = 2; i >= 0; i--) {
if (i == 2) {
status = pthread_mutex_lock(&mutex[i]);
if (status != 0)
err_abort(status, "First lock");
}
else {
if (backoff)
status = pthread_mutex_trylock(&mutex[i]);
else
status = pthread_mutex_lock(&mutex[i]);
if (status == EBUSY) {
backoffs++;
DPRINTF((" [backward locker backing off at %d]\n", i));
for (; i < 3; i++) {
status = pthread_mutex_unlock(&mutex[i]);
if (status != 0)
err_abort(status, "Backoff");
}
}
/*
* Report that we got 'em, and unlock to try again.
*/
printf (
"lock backward got all locks, %d backoffs\n", backoffs);
pthread_mutex_unlock (&mutex[0]);
pthread_mutex_unlock (&mutex[1]);
pthread_mutex_unlock (&mutex[2]);
sched_yield ();
else {
if (status != 0)
err_abort(status, "Lock mutex");
DPRINTF((" backward locker got %d\n", i));
}
}
/*
* Yield processor, if needed to be sure locks get
* interleaved on a uniprocessor.
*/
if (yield_flag) {
if (yield_flag > 0)
sched_yield();
else
sleep(1);
}
}
return NULL;
/*
* Report that we got 'em, and unlock to try again.
*/
printf("lock backward got all locks, %d backoffs\n", backoffs);
pthread_mutex_unlock(&mutex[0]);
pthread_mutex_unlock(&mutex[1]);
pthread_mutex_unlock(&mutex[2]);
sched_yield();
}
return NULL;
}
int main (int argc, char *argv[])
int
main(int argc, char* argv[])
{
pthread_t forward, backward;
int status;
pthread_t forward, backward;
int status;
#ifdef sun
/*
* On Solaris 2.5, threads are not timesliced. To ensure
* that our threads can run concurrently, we need to
* increase the concurrency level.
*/
DPRINTF (("Setting concurrency level to 2\n"));
thr_setconcurrency (2);
/*
* On Solaris 2.5, threads are not timesliced. To ensure
* that our threads can run concurrently, we need to
* increase the concurrency level.
*/
DPRINTF(("Setting concurrency level to 2\n"));
thr_setconcurrency(2);
#endif
/*
* If the first argument is absent, or nonzero, a backoff
* algorithm will be used to avoid deadlock. If the first
* argument is zero, the program will deadlock on a lock
* "collision."
*/
if (argc > 1)
backoff = atoi (argv[1]);
/*
* If the first argument is absent, or nonzero, a backoff
* algorithm will be used to avoid deadlock. If the first
* argument is zero, the program will deadlock on a lock
* "collision."
*/
if (argc > 1)
backoff = atoi(argv[1]);
/*
* If the second argument is absent, or zero, the two
* threads run "at speed." On some systems, especially
* uniprocessors, one thread may complete before the other
* has a chance to run, and you won't see a deadlock or
* backoffs. In that case, try running with the argument set
* to a positive number to cause the threads to call
* sched_yield() at each lock; or, to make it even more
* obvious, set to a negative number to cause the threads to
* call sleep(1) instead.
*/
if (argc > 2)
yield_flag = atoi (argv[2]);
status = pthread_create (
&forward, NULL, lock_forward, NULL);
if (status != 0)
err_abort (status, "Create forward");
status = pthread_create (
&backward, NULL, lock_backward, NULL);
if (status != 0)
err_abort (status, "Create backward");
pthread_exit (NULL);
/*
* If the second argument is absent, or zero, the two
* threads run "at speed." On some systems, especially
* uniprocessors, one thread may complete before the other
* has a chance to run, and you won't see a deadlock or
* backoffs. In that case, try running with the argument set
* to a positive number to cause the threads to call
* sched_yield() at each lock; or, to make it even more
* obvious, set to a negative number to cause the threads to
* call sleep(1) instead.
*/
if (argc > 2)
yield_flag = atoi(argv[2]);
status = pthread_create(&forward, NULL, lock_forward, NULL);
if (status != 0)
err_abort(status, "Create forward");
status = pthread_create(&backward, NULL, lock_backward, NULL);
if (status != 0)
err_abort(status, "Create backward");
pthread_exit(NULL);
}

View File

@@ -8,88 +8,87 @@
#include "errors.h"
typedef struct my_struct_tag {
pthread_mutex_t mutex; /* Protects access to value */
pthread_cond_t cond; /* Signals change to value */
int value; /* Access protected by mutex */
pthread_mutex_t mutex; /* Protects access to value */
pthread_cond_t cond; /* Signals change to value */
int value; /* Access protected by mutex */
} my_struct_t;
my_struct_t data = {
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
int hibernation = 1; /* Default to 1 second */
int hibernation = 1; /* Default to 1 second */
/*
* Thread start routine. It will set the main thread's predicate
* and signal the condition variable.
*/
void *
wait_thread (void *arg)
void*
wait_thread(void* arg)
{
int status;
int status;
sleep (hibernation);
status = pthread_mutex_lock (&data.mutex);
if (status != 0)
err_abort (status, "Lock mutex");
data.value = 1; /* Set predicate */
status = pthread_cond_signal (&data.cond);
if (status != 0)
err_abort (status, "Signal condition");
status = pthread_mutex_unlock (&data.mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
return NULL;
sleep(hibernation);
status = pthread_mutex_lock(&data.mutex);
if (status != 0)
err_abort(status, "Lock mutex");
data.value = 1; /* Set predicate */
status = pthread_cond_signal(&data.cond);
if (status != 0)
err_abort(status, "Signal condition");
status = pthread_mutex_unlock(&data.mutex);
if (status != 0)
err_abort(status, "Unlock mutex");
return NULL;
}
int main (int argc, char *argv[])
int
main(int argc, char* argv[])
{
int status;
pthread_t wait_thread_id;
struct timespec timeout;
int status;
pthread_t wait_thread_id;
struct timespec timeout;
/*
* If an argument is specified, interpret it as the number
* of seconds for wait_thread to sleep before signaling the
* condition variable. You can play with this to see the
* condition wait below time out or wake normally.
*/
if (argc > 1)
hibernation = atoi (argv[1]);
/*
* If an argument is specified, interpret it as the number
* of seconds for wait_thread to sleep before signaling the
* condition variable. You can play with this to see the
* condition wait below time out or wake normally.
*/
if (argc > 1)
hibernation = atoi(argv[1]);
/*
* Create wait_thread.
*/
status = pthread_create (&wait_thread_id, NULL, wait_thread, NULL);
if (status != 0)
err_abort (status, "Create wait thread");
/*
* Create wait_thread.
*/
status = pthread_create(&wait_thread_id, NULL, wait_thread, NULL);
if (status != 0)
err_abort(status, "Create wait thread");
/*
* Wait on the condition variable for 2 seconds, or until
* signaled by the wait_thread. Normally, wait_thread
* should signal. If you raise "hibernation" above 2
* seconds, it will time out.
*/
timeout.tv_sec = time (NULL) + 2;
timeout.tv_nsec = 0;
status = pthread_mutex_lock (&data.mutex);
if (status != 0)
err_abort (status, "Lock mutex");
/*
* Wait on the condition variable for 2 seconds, or until
* signaled by the wait_thread. Normally, wait_thread
* should signal. If you raise "hibernation" above 2
* seconds, it will time out.
*/
timeout.tv_sec = time(NULL) + 2;
timeout.tv_nsec = 0;
status = pthread_mutex_lock(&data.mutex);
if (status != 0)
err_abort(status, "Lock mutex");
while (data.value == 0) {
status = pthread_cond_timedwait (
&data.cond, &data.mutex, &timeout);
if (status == ETIMEDOUT) {
printf ("Condition wait timed out.\n");
break;
}
else if (status != 0)
err_abort (status, "Wait on condition");
while (data.value == 0) {
status = pthread_cond_timedwait(&data.cond, &data.mutex, &timeout);
if (status == ETIMEDOUT) {
printf("Condition wait timed out.\n");
break;
}
else if (status != 0)
err_abort(status, "Wait on condition");
}
if (data.value != 0)
printf ("Condition was signaled.\n");
status = pthread_mutex_unlock (&data.mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
return 0;
if (data.value != 0)
printf("Condition was signaled.\n");
status = pthread_mutex_unlock(&data.mutex);
if (status != 0)
err_abort(status, "Unlock mutex");
return 0;
}

View File

@@ -10,31 +10,32 @@
* Define a structure, with a mutex and condition variable.
*/
typedef struct my_struct_tag {
pthread_mutex_t mutex; /* Protects access to value */
pthread_cond_t cond; /* Signals change to value */
int value; /* Access protected by mutex */
pthread_mutex_t mutex; /* Protects access to value */
pthread_cond_t cond; /* Signals change to value */
int value; /* Access protected by mutex */
} my_struct_t;
int main (int argc, char *argv[])
int
main(int argc, char* argv[])
{
my_struct_t *data;
int status;
my_struct_t* data;
int status;
data = malloc (sizeof (my_struct_t));
if (data == NULL)
errno_abort ("Allocate structure");
status = pthread_mutex_init (&data->mutex, NULL);
if (status != 0)
err_abort (status, "Init mutex");
status = pthread_cond_init (&data->cond, NULL);
if (status != 0)
err_abort (status, "Init condition");
status = pthread_cond_destroy (&data->cond);
if (status != 0)
err_abort (status, "Destroy condition");
status = pthread_mutex_destroy (&data->mutex);
if (status != 0)
err_abort (status, "Destroy mutex");
(void)free (data);
return status;
data = malloc(sizeof(my_struct_t));
if (data == NULL)
errno_abort("Allocate structure");
status = pthread_mutex_init(&data->mutex, NULL);
if (status != 0)
err_abort(status, "Init mutex");
status = pthread_cond_init(&data->cond, NULL);
if (status != 0)
err_abort(status, "Init condition");
status = pthread_cond_destroy(&data->cond);
if (status != 0)
err_abort(status, "Destroy condition");
status = pthread_mutex_destroy(&data->mutex);
if (status != 0)
err_abort(status, "Destroy mutex");
(void) free(data);
return status;
}

View File

@@ -13,15 +13,15 @@
* attributes.
*/
typedef struct my_struct_tag {
pthread_mutex_t mutex; /* Protects access to value */
pthread_cond_t cond; /* Signals change to value */
int value; /* Access protected by mutex */
pthread_mutex_t mutex; /* Protects access to value */
pthread_cond_t cond; /* Signals change to value */
int value; /* Access protected by mutex */
} my_struct_t;
my_struct_t data = {
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
int main (int argc, char *argv[])
int
main(int argc, char* argv[])
{
return 0;
return 0;
}

View File

@@ -10,24 +10,25 @@
* Define a structure, with a mutex.
*/
typedef struct my_struct_tag {
pthread_mutex_t mutex; /* Protects access to value */
int value; /* Access protected by mutex */
pthread_mutex_t mutex; /* Protects access to value */
int value; /* Access protected by mutex */
} my_struct_t;
int main (int argc, char *argv[])
int
main(int argc, char* argv[])
{
my_struct_t *data;
int status;
my_struct_t* data;
int status;
data = malloc (sizeof (my_struct_t));
if (data == NULL)
errno_abort ("Allocate structure");
status = pthread_mutex_init (&data->mutex, NULL);
if (status != 0)
err_abort (status, "Init mutex");
status = pthread_mutex_destroy (&data->mutex);
if (status != 0)
err_abort (status, "Destroy mutex");
(void)free (data);
return status;
data = malloc(sizeof(my_struct_t));
if (data == NULL)
errno_abort("Allocate structure");
status = pthread_mutex_init(&data->mutex, NULL);
if (status != 0)
err_abort(status, "Init mutex");
status = pthread_mutex_destroy(&data->mutex);
if (status != 0)
err_abort(status, "Destroy mutex");
(void) free(data);
return status;
}

View File

@@ -11,13 +11,14 @@
* same as using pthread_mutex_init, with the default attributes.
*/
typedef struct my_struct_tag {
pthread_mutex_t mutex; /* Protects access to value */
int value; /* Access protected by mutex */
pthread_mutex_t mutex; /* Protects access to value */
int value; /* Access protected by mutex */
} my_struct_t;
my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, 0};
int main (int argc, char *argv[])
int
main(int argc, char* argv[])
{
return 0;
return 0;
}

View File

@@ -24,7 +24,9 @@ time_t end_time;
* Thread start routine that repeatedly locks a mutex and
* increments a counter.
*/
void *counter_thread(void *arg) {
void*
counter_thread(void* arg)
{
int status;
int spin;
@@ -36,11 +38,13 @@ void *counter_thread(void *arg) {
*/
while (time(NULL) < end_time) {
status = pthread_mutex_lock(&mutex);
if (status != 0) err_abort(status, "Lock mutex");
if (status != 0)
err_abort(status, "Lock mutex");
for (spin = 0; spin < SPIN; spin++) counter++;
sleep(4);
status = pthread_mutex_unlock(&mutex);
if (status != 0) err_abort(status, "Unlock mutex");
if (status != 0)
err_abort(status, "Unlock mutex");
sleep(1);
}
printf("Counter is %#lx\n", counter);
@@ -52,7 +56,9 @@ void *counter_thread(void *arg) {
* seconds, try to lock the mutex and read the counter. If the
* trylock fails, skip this cycle.
*/
void *monitor_thread(void *arg) {
void*
monitor_thread(void* arg)
{
int status;
int misses = 0;
@@ -64,18 +70,23 @@ void *monitor_thread(void *arg) {
sleep(3);
status = pthread_mutex_trylock(&mutex);
if (status != EBUSY) {
if (status != 0) err_abort(status, "Trylock mutex");
if (status != 0)
err_abort(status, "Trylock mutex");
printf("Counter is %ld\n", counter / SPIN);
status = pthread_mutex_unlock(&mutex);
if (status != 0) err_abort(status, "Unlock mutex");
} else
if (status != 0)
err_abort(status, "Unlock mutex");
}
else
misses++; /* Count "misses" on the lock */
}
printf("Monitor thread missed update %d times.\n", misses);
return NULL;
}
int main(int argc, char *argv[]) {
int
main(int argc, char* argv[])
{
int status;
pthread_t counter_thread_id;
pthread_t monitor_thread_id;
@@ -91,13 +102,17 @@ int main(int argc, char *argv[]) {
#endif
end_time = time(NULL) + 60; /* Run for 1 minute */
status = pthread_create(&counter_thread_id, NULL, counter_thread, NULL);
if (status != 0) err_abort(status, "Create counter thread");
status = pthread_create(&counter_thread_id, NULL, counter_thread, NULL);
if (status != 0)
err_abort(status, "Create counter thread");
status = pthread_create(&monitor_thread_id, NULL, monitor_thread, NULL);
if (status != 0) err_abort(status, "Create monitor thread");
if (status != 0)
err_abort(status, "Create monitor thread");
status = pthread_join(counter_thread_id, NULL);
if (status != 0) err_abort(status, "Join counter thread");
if (status != 0)
err_abort(status, "Join counter thread");
status = pthread_join(monitor_thread_id, NULL);
if (status != 0) err_abort(status, "Join monitor thread");
if (status != 0)
err_abort(status, "Join monitor thread");
return 0;
}