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

104
.clang-format Normal file
View File

@@ -0,0 +1,104 @@
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: TopLevelDefinitions
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BreakBeforeBraces : Custom
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeInheritanceComma: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: false
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 2
UseTab: Never

View File

@@ -73,7 +73,13 @@ ch04/pipe_cpp.cpp
NAMES_CXX=$(SOURCES_CXX:.cpp=) NAMES_CXX=$(SOURCES_CXX:.cpp=)
PROGRAMS_CXX=$(addprefix $(BIN)/, $(NAMES_CXX)) PROGRAMS_CXX=$(addprefix $(BIN)/, $(NAMES_CXX))
all: dirs ${PROGRAMS_C} ${PROGRAMS_CXX} all: format dirs ${PROGRAMS_C} ${PROGRAMS_CXX}
format:
#clang-format -i $(SOURCE)/*.c*
#clang-format -i $(SOURCE)/*.h*
clang-format -i $(SOURCE)/*/*.c*
clang-format -i $(SOURCE)/*/*.h*
dirs: dirs:
mkdir -p $(BIN) mkdir -p $(BIN)

View File

@@ -7,28 +7,31 @@
*/ */
#include "errors.h" #include "errors.h"
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int seconds; int seconds;
char line[128]; char line[128];
char message[64]; char message[64];
while (1) { while (1) {
printf ("Alarm> "); printf("Alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (fgets(line, sizeof(line), stdin) == NULL)
if (strlen (line) <= 1) continue; exit(0);
if (strlen(line) <= 1)
continue;
/* /*
* Parse input line into seconds (%d) and a message * Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters * (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace. * separated from the seconds by whitespace.
*/ */
if (sscanf (line, "%d %64[^\n]", if (sscanf(line, "%d %64[^\n]", &seconds, message) < 2) {
&seconds, message) < 2) { fprintf(stderr, "Bad command\n");
fprintf (stderr, "Bad command\n"); }
} else { else {
sleep (seconds); sleep(seconds);
printf ("(%d) %s\n", seconds, message); printf("(%d) %s\n", seconds, message);
} }
} }
} }

View File

@@ -8,7 +8,8 @@
#include <wait.h> #include <wait.h>
#include "errors.h" #include "errors.h"
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int status; int status;
char line[128]; char line[128];
@@ -17,39 +18,42 @@ int main (int argc, char *argv[])
char message[64]; char message[64];
while (1) { while (1) {
printf ("Alarm> "); printf("Alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (fgets(line, sizeof(line), stdin) == NULL)
if (strlen (line) <= 1) continue; exit(0);
if (strlen(line) <= 1)
continue;
/* /*
* Parse input line into seconds (%d) and a message * Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters * (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace. * separated from the seconds by whitespace.
*/ */
if (sscanf (line, "%d %64[^\n]", if (sscanf(line, "%d %64[^\n]", &seconds, message) < 2) {
&seconds, message) < 2) { fprintf(stderr, "Bad command\n");
fprintf (stderr, "Bad command\n"); }
} else { else {
pid = fork (); pid = fork();
if (pid == (pid_t)-1) if (pid == (pid_t) -1)
errno_abort ("Fork"); errno_abort("Fork");
if (pid == (pid_t)0) { if (pid == (pid_t) 0) {
/* /*
* If we're in the child, wait and then print a message * If we're in the child, wait and then print a message
*/ */
sleep (seconds); sleep(seconds);
printf ("(%d) %s\n", seconds, message); printf("(%d) %s\n", seconds, message);
exit (0); exit(0);
} else { }
else {
/* /*
* In the parent, call waitpid() to collect any children that * In the parent, call waitpid() to collect any children that
* have already terminated. * have already terminated.
*/ */
do { do {
pid = waitpid ((pid_t)-1, NULL, WNOHANG); pid = waitpid((pid_t) -1, NULL, WNOHANG);
if (pid == (pid_t)-1) if (pid == (pid_t) -1)
errno_abort ("Wait for child"); errno_abort("Wait for child");
} while (pid != (pid_t)0); } while (pid != (pid_t) 0);
} }
} }
} }

View File

@@ -12,48 +12,51 @@ typedef struct alarm_tag {
char message[64]; char message[64];
} alarm_t; } alarm_t;
void *alarm_thread (void *arg) void*
alarm_thread(void* arg)
{ {
alarm_t *alarm = (alarm_t*)arg; alarm_t* alarm = (alarm_t*) arg;
int status; int status;
status = pthread_detach (pthread_self ()); status = pthread_detach(pthread_self());
if (status != 0) if (status != 0)
err_abort (status, "Detach thread"); err_abort(status, "Detach thread");
sleep (alarm->seconds); sleep(alarm->seconds);
printf ("(%d) %s\n", alarm->seconds, alarm->message); printf("(%d) %s\n", alarm->seconds, alarm->message);
free (alarm); free(alarm);
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int status; int status;
char line[128]; char line[128];
alarm_t *alarm; alarm_t* alarm;
pthread_t thread; pthread_t thread;
while (1) { while (1) {
printf ("Alarm> "); printf("Alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (fgets(line, sizeof(line), stdin) == NULL)
if (strlen (line) <= 1) continue; exit(0);
alarm = (alarm_t*)malloc (sizeof (alarm_t)); if (strlen(line) <= 1)
continue;
alarm = (alarm_t*) malloc(sizeof(alarm_t));
if (alarm == NULL) if (alarm == NULL)
errno_abort ("Allocate alarm"); errno_abort("Allocate alarm");
/* /*
* Parse input line into seconds (%d) and a message * Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters * (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace. * separated from the seconds by whitespace.
*/ */
if (sscanf (line, "%d %64[^\n]", if (sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message) < 2) {
&alarm->seconds, alarm->message) < 2) { fprintf(stderr, "Bad command\n");
fprintf (stderr, "Bad command\n"); free(alarm);
free (alarm); }
} else { else {
status = pthread_create ( status = pthread_create(&thread, NULL, alarm_thread, alarm);
&thread, NULL, alarm_thread, alarm);
if (status != 0) if (status != 0)
err_abort (status, "Create alarm thread"); err_abort(status, "Create alarm thread");
} }
} }
} }

View File

@@ -4,11 +4,12 @@
* Demonstrate detection of errors from a typical POSIX 1003.1c-1995 * Demonstrate detection of errors from a typical POSIX 1003.1c-1995
* function, pthread_join. * function, pthread_join.
*/ */
#include <errno.h>
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread; pthread_t thread;
int status; int status;
@@ -22,8 +23,8 @@ int main (int argc, char *argv[])
* implementation may either return EDEADLK (self-deadlock), * implementation may either return EDEADLK (self-deadlock),
* or it may hang. If it hangs, quit and try again. * or it may hang. If it hangs, quit and try again.
*/ */
status = pthread_join (thread, NULL); status = pthread_join(thread, NULL);
if (status != 0) if (status != 0)
fprintf (stderr, "error %d: %s\n", status, strerror (status)); fprintf(stderr, "error %d: %s\n", status, strerror(status));
return status; return status;
} }

View File

@@ -7,22 +7,24 @@
#include <pthread.h> #include <pthread.h>
#include "errors.h" #include "errors.h"
void *hello_world (void *arg) void*
hello_world(void* arg)
{ {
printf ("Hello world\n"); printf("Hello world\n");
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t hello_id; pthread_t hello_id;
int status; int status;
status = pthread_create (&hello_id, NULL, hello_world, NULL); status = pthread_create(&hello_id, NULL, hello_world, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_join (hello_id, NULL); status = pthread_join(hello_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
return 0; return 0;
} }

View File

@@ -10,29 +10,29 @@
/* /*
* Thread start routine. * Thread start routine.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
printf("Inside thread %i\n", pthread_self()); printf("Inside thread %i\n", pthread_self());
return arg; return arg;
} }
main (int argc, char *argv[]) main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
void *thread_result; void* thread_result;
int status; int status;
printf("Inside thread %i\n", pthread_self()); printf("Inside thread %i\n", pthread_self());
status = pthread_create ( status = pthread_create(&thread_id, NULL, thread_routine, NULL);
&thread_id, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
sleep(1.0); sleep(1.0);
printf("Main thread created thread %i\n", thread_id); printf("Main thread created thread %i\n", thread_id);
status = pthread_join (thread_id, &thread_result); status = pthread_join(thread_id, &thread_result);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
if (thread_result == NULL) if (thread_result == NULL)
return 0; return 0;
else else

View File

@@ -10,22 +10,24 @@
/* /*
* Thread start routine that writes a message. * Thread start routine that writes a message.
*/ */
void *writer_thread (void *arg) void*
writer_thread(void* arg)
{ {
sleep (5); sleep(5);
printf ("Thread I/O\n"); printf("Thread I/O\n");
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t writer_id; pthread_t writer_id;
char *input, buffer[64]; char *input, buffer[64];
pthread_create (&writer_id, NULL, writer_thread, NULL); pthread_create(&writer_id, NULL, writer_thread, NULL);
input = fgets (buffer, 64, stdin); input = fgets(buffer, 64, stdin);
if (input != NULL) if (input != NULL)
printf ("You said %s", buffer); printf("You said %s", buffer);
pthread_exit (NULL); pthread_exit(NULL);
return 0; return 0;
} }

View File

@@ -22,7 +22,7 @@
* been on the list. * been on the list.
*/ */
typedef struct alarm_tag { typedef struct alarm_tag {
struct alarm_tag *link; struct alarm_tag* link;
int seconds; int seconds;
time_t time; /* seconds from EPOCH */ time_t time; /* seconds from EPOCH */
char message[64]; char message[64];
@@ -30,13 +30,14 @@ typedef struct alarm_tag {
pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t alarm_cond = PTHREAD_COND_INITIALIZER; pthread_cond_t alarm_cond = PTHREAD_COND_INITIALIZER;
alarm_t *alarm_list = NULL; alarm_t* alarm_list = NULL;
time_t current_alarm = 0; time_t current_alarm = 0;
/* /*
* Insert alarm entry on list, in order. * Insert alarm entry on list, in order.
*/ */
void alarm_insert (alarm_t *alarm) void
alarm_insert(alarm_t* alarm)
{ {
int status; int status;
alarm_t **last, *next; alarm_t **last, *next;
@@ -68,11 +69,11 @@ void alarm_insert (alarm_t *alarm)
alarm->link = NULL; alarm->link = NULL;
} }
#ifdef DEBUG #ifdef DEBUG
printf ("[list: "); printf("[list: ");
for (next = alarm_list; next != NULL; next = next->link) for (next = alarm_list; next != NULL; next = next->link)
printf ("%d(%d)[\"%s\"] ", next->time, printf(
next->time - time (NULL), next->message); "%d(%d)[\"%s\"] ", next->time, next->time - time(NULL), next->message);
printf ("]\n"); printf("]\n");
#endif #endif
/* /*
* Wake the alarm thread if it is not busy (that is, if * Wake the alarm thread if it is not busy (that is, if
@@ -82,18 +83,19 @@ void alarm_insert (alarm_t *alarm)
*/ */
if (current_alarm == 0 || alarm->time < current_alarm) { if (current_alarm == 0 || alarm->time < current_alarm) {
current_alarm = alarm->time; current_alarm = alarm->time;
status = pthread_cond_signal (&alarm_cond); status = pthread_cond_signal(&alarm_cond);
if (status != 0) if (status != 0)
err_abort (status, "Signal cond"); err_abort(status, "Signal cond");
} }
} }
/* /*
* The alarm thread's start routine. * The alarm thread's start routine.
*/ */
void *alarm_thread (void *arg) void*
alarm_thread(void* arg)
{ {
alarm_t *alarm; alarm_t* alarm;
struct timespec cond_time; struct timespec cond_time;
time_t now; time_t now;
int status, expired; int status, expired;
@@ -104,9 +106,9 @@ void *alarm_thread (void *arg)
* at the start -- it will be unlocked during condition * at the start -- it will be unlocked during condition
* waits, so the main thread can insert alarms. * waits, so the main thread can insert alarms.
*/ */
status = pthread_mutex_lock (&alarm_mutex); status = pthread_mutex_lock(&alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
while (1) { while (1) {
/* /*
* If the alarm list is empty, wait until an alarm is * If the alarm list is empty, wait until an alarm is
@@ -115,84 +117,88 @@ void *alarm_thread (void *arg)
*/ */
current_alarm = 0; current_alarm = 0;
while (alarm_list == NULL) { while (alarm_list == NULL) {
status = pthread_cond_wait (&alarm_cond, &alarm_mutex); status = pthread_cond_wait(&alarm_cond, &alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait on cond"); err_abort(status, "Wait on cond");
} }
alarm = alarm_list; alarm = alarm_list;
alarm_list = alarm->link; alarm_list = alarm->link;
now = time (NULL); now = time(NULL);
expired = 0; expired = 0;
if (alarm->time > now) { if (alarm->time > now) {
#ifdef DEBUG #ifdef DEBUG
printf ("[waiting: %d(%d)\"%s\"]\n", alarm->time, printf("[waiting: %d(%d)\"%s\"]\n",
alarm->time - time (NULL), alarm->message); alarm->time,
alarm->time - time(NULL),
alarm->message);
#endif #endif
cond_time.tv_sec = alarm->time; cond_time.tv_sec = alarm->time;
cond_time.tv_nsec = 0; cond_time.tv_nsec = 0;
current_alarm = alarm->time; current_alarm = alarm->time;
while (current_alarm == alarm->time) { while (current_alarm == alarm->time) {
status = pthread_cond_timedwait ( status = pthread_cond_timedwait(&alarm_cond, &alarm_mutex, &cond_time);
&alarm_cond, &alarm_mutex, &cond_time);
if (status == ETIMEDOUT) { if (status == ETIMEDOUT) {
expired = 1; expired = 1;
break; break;
} }
if (status != 0) if (status != 0)
err_abort (status, "Cond timedwait"); err_abort(status, "Cond timedwait");
} }
if (!expired) if (!expired)
alarm_insert (alarm); alarm_insert(alarm);
} else }
else
expired = 1; expired = 1;
if (expired) { if (expired) {
printf ("(%d) %s\n", alarm->seconds, alarm->message); printf("(%d) %s\n", alarm->seconds, alarm->message);
free (alarm); free(alarm);
} }
} }
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int status; int status;
char line[128]; char line[128];
alarm_t *alarm; alarm_t* alarm;
pthread_t thread; pthread_t thread;
status = pthread_create ( status = pthread_create(&thread, NULL, alarm_thread, NULL);
&thread, NULL, alarm_thread, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create alarm thread"); err_abort(status, "Create alarm thread");
while (1) { while (1) {
printf ("Alarm> "); printf("Alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (fgets(line, sizeof(line), stdin) == NULL)
if (strlen (line) <= 1) continue; exit(0);
alarm = (alarm_t*)malloc (sizeof (alarm_t)); if (strlen(line) <= 1)
continue;
alarm = (alarm_t*) malloc(sizeof(alarm_t));
if (alarm == NULL) if (alarm == NULL)
errno_abort ("Allocate alarm"); errno_abort("Allocate alarm");
/* /*
* Parse input line into seconds (%d) and a message * Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters * (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace. * separated from the seconds by whitespace.
*/ */
if (sscanf (line, "%d %64[^\n]", if (sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message) < 2) {
&alarm->seconds, alarm->message) < 2) { fprintf(stderr, "Bad command\n");
fprintf (stderr, "Bad command\n"); free(alarm);
free (alarm); }
} else { else {
status = pthread_mutex_lock (&alarm_mutex); status = pthread_mutex_lock(&alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
alarm->time = time (NULL) + alarm->seconds; alarm->time = time(NULL) + alarm->seconds;
/* /*
* Insert the new alarm into the list of alarms, * Insert the new alarm into the list of alarms,
* sorted by expiration time. * sorted by expiration time.
*/ */
alarm_insert (alarm); alarm_insert(alarm);
status = pthread_mutex_unlock (&alarm_mutex); status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
} }
} }
} }

View File

@@ -22,21 +22,22 @@
* been on the list. * been on the list.
*/ */
typedef struct alarm_tag { typedef struct alarm_tag {
struct alarm_tag *link; struct alarm_tag* link;
int seconds; int seconds;
time_t time; /* seconds from EPOCH */ time_t time; /* seconds from EPOCH */
char message[64]; char message[64];
} alarm_t; } alarm_t;
pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;
alarm_t *alarm_list = NULL; alarm_t* alarm_list = NULL;
/* /*
* The alarm thread's start routine. * The alarm thread's start routine.
*/ */
void *alarm_thread (void *arg) void*
alarm_thread(void* arg)
{ {
alarm_t *alarm; alarm_t* alarm;
int sleep_time; int sleep_time;
time_t now; time_t now;
int status; int status;
@@ -46,9 +47,9 @@ void *alarm_thread (void *arg)
* be disintegrated when the process exits. * be disintegrated when the process exits.
*/ */
while (1) { while (1) {
status = pthread_mutex_lock (&alarm_mutex); status = pthread_mutex_lock(&alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
alarm = alarm_list; alarm = alarm_list;
/* /*
@@ -63,14 +64,14 @@ void *alarm_thread (void *arg)
sleep_time = 1; sleep_time = 1;
else { else {
alarm_list = alarm->link; alarm_list = alarm->link;
now = time (NULL); now = time(NULL);
if (alarm->time <= now) if (alarm->time <= now)
sleep_time = 0; sleep_time = 0;
else else
sleep_time = alarm->time - now; sleep_time = alarm->time - now;
#ifdef DEBUG #ifdef DEBUG
printf ("[waiting: %d(%d)\"%s\"]\n", alarm->time, printf(
sleep_time, alarm->message); "[waiting: %d(%d)\"%s\"]\n", alarm->time, sleep_time, alarm->message);
#endif #endif
} }
@@ -82,58 +83,60 @@ void *alarm_thread (void *arg)
* readied by user input, without delaying the message * readied by user input, without delaying the message
* if there's no input. * if there's no input.
*/ */
status = pthread_mutex_unlock (&alarm_mutex); status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
if (sleep_time > 0) if (sleep_time > 0)
sleep (sleep_time); sleep(sleep_time);
else else
sched_yield (); sched_yield();
/* /*
* If a timer expired, print the message and free the * If a timer expired, print the message and free the
* structure. * structure.
*/ */
if (alarm != NULL) { if (alarm != NULL) {
printf ("(%d) %s\n", alarm->seconds, alarm->message); printf("(%d) %s\n", alarm->seconds, alarm->message);
free (alarm); free(alarm);
} }
} }
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int status; int status;
char line[128]; char line[128];
alarm_t *alarm, **last, *next; alarm_t *alarm, **last, *next;
pthread_t thread; pthread_t thread;
status = pthread_create ( status = pthread_create(&thread, NULL, alarm_thread, NULL);
&thread, NULL, alarm_thread, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create alarm thread"); err_abort(status, "Create alarm thread");
while (1) { while (1) {
printf ("alarm> "); printf("alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (fgets(line, sizeof(line), stdin) == NULL)
if (strlen (line) <= 1) continue; exit(0);
alarm = (alarm_t*)malloc (sizeof (alarm_t)); if (strlen(line) <= 1)
continue;
alarm = (alarm_t*) malloc(sizeof(alarm_t));
if (alarm == NULL) if (alarm == NULL)
errno_abort ("Allocate alarm"); errno_abort("Allocate alarm");
/* /*
* Parse input line into seconds (%d) and a message * Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters * (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace. * separated from the seconds by whitespace.
*/ */
if (sscanf (line, "%d %64[^\n]", if (sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message) < 2) {
&alarm->seconds, alarm->message) < 2) { fprintf(stderr, "Bad command\n");
fprintf (stderr, "Bad command\n"); free(alarm);
free (alarm); }
} else { else {
status = pthread_mutex_lock (&alarm_mutex); status = pthread_mutex_lock(&alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
alarm->time = time (NULL) + alarm->seconds; alarm->time = time(NULL) + alarm->seconds;
/* /*
* Insert the new alarm into the list of alarms, * Insert the new alarm into the list of alarms,
@@ -161,15 +164,17 @@ int main (int argc, char *argv[])
alarm->link = NULL; alarm->link = NULL;
} }
#ifdef DEBUG #ifdef DEBUG
printf ("[list: "); printf("[list: ");
for (next = alarm_list; next != NULL; next = next->link) for (next = alarm_list; next != NULL; next = next->link)
printf ("%d(%d)[\"%s\"] ", next->time, printf("%d(%d)[\"%s\"] ",
next->time - time (NULL), next->message); next->time,
printf ("]\n"); next->time - time(NULL),
next->message);
printf("]\n");
#endif #endif
status = pthread_mutex_unlock (&alarm_mutex); status = pthread_mutex_unlock(&alarm_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
} }
} }
} }

View File

@@ -39,7 +39,9 @@ std::list<alarm_t> alarm_list;
/* /*
* The alarm thread's start routine. * The alarm thread's start routine.
*/ */
void *alarm_thread(void *arg) { void*
alarm_thread(void* arg)
{
int sleep_time; int sleep_time;
time_t now; time_t now;
int status; int status;
@@ -50,7 +52,8 @@ void *alarm_thread(void *arg) {
*/ */
while (1) { while (1) {
status = pthread_mutex_lock(&alarm_mutex); 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; sleep_time = 0;
@@ -59,7 +62,8 @@ void *alarm_thread(void *arg) {
if (it->time <= now) { if (it->time <= now) {
printf("(%d) %s\n", it->seconds, it->message); printf("(%d) %s\n", it->seconds, it->message);
it = alarm_list.erase(it); it = alarm_list.erase(it);
} else { }
else {
sleep_time = MIN(it->time - now, sleep_time); sleep_time = MIN(it->time - now, sleep_time);
++it; ++it;
} }
@@ -74,7 +78,8 @@ void *alarm_thread(void *arg) {
* if there's no input. * if there's no input.
*/ */
status = pthread_mutex_unlock(&alarm_mutex); 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) if (sleep_time > 0)
sleep(sleep_time); sleep(sleep_time);
else else
@@ -82,17 +87,22 @@ void *alarm_thread(void *arg) {
} }
} }
int main(int argc, char *argv[]) { int
main(int argc, char* argv[])
{
int status; int status;
char line[128]; char line[128];
pthread_t thread; pthread_t thread;
status = pthread_create(&thread, NULL, alarm_thread, NULL); 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) { while (1) {
printf("alarm> "); printf("alarm> ");
if (fgets(line, sizeof(line), stdin) == NULL) exit(0); if (fgets(line, sizeof(line), stdin) == NULL)
if (strlen(line) <= 1) continue; exit(0);
if (strlen(line) <= 1)
continue;
alarm_t alarm; alarm_t alarm;
/* /*
@@ -102,11 +112,13 @@ int main(int argc, char *argv[]) {
*/ */
if (sscanf(line, "%d %64[^\n]", &alarm.seconds, alarm.message) < 2) { if (sscanf(line, "%d %64[^\n]", &alarm.seconds, alarm.message) < 2) {
fprintf(stderr, "Bad command\n"); fprintf(stderr, "Bad command\n");
} else { }
else {
alarm.time = time(NULL) + alarm.seconds; alarm.time = time(NULL) + alarm.seconds;
status = pthread_mutex_lock(&alarm_mutex); 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. * Insert the new alarm into the list of alarms.
@@ -115,13 +127,16 @@ int main(int argc, char *argv[]) {
#ifdef DEBUG #ifdef DEBUG
printf("[list: "); printf("[list: ");
for (const auto &iAlarm : alarm_list) for (const auto& iAlarm : alarm_list)
printf("%d(%d)[\"%s\"] ", iAlarm.time, iAlarm.time - time(NULL), printf("%d(%d)[\"%s\"] ",
iAlarm.time,
iAlarm.time - time(NULL),
iAlarm.message); iAlarm.message);
printf("]\n"); printf("]\n");
#endif #endif
status = pthread_mutex_unlock(&alarm_mutex); 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,11 +17,9 @@
/* /*
* Initialize a static array of 3 mutexes. * Initialize a static array of 3 mutexes.
*/ */
pthread_mutex_t mutex[3] = { pthread_mutex_t mutex[3] = {PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER};
PTHREAD_MUTEX_INITIALIZER
};
int backoff = 1; /* Whether to backoff or deadlock */ int backoff = 1; /* Whether to backoff or deadlock */
int yield_flag = 0; /* 0: no yield, >0: yield, <0: sleep */ int yield_flag = 0; /* 0: no yield, >0: yield, <0: sleep */
@@ -31,7 +29,8 @@ int yield_flag = 0; /* 0: no yield, >0: yield, <0: sleep */
* order, to ensure a conflict with lock_reverse, which does the * order, to ensure a conflict with lock_reverse, which does the
* opposite. * opposite.
*/ */
void *lock_forward (void *arg) void*
lock_forward(void* arg)
{ {
int i, iterate, backoffs; int i, iterate, backoffs;
int status; int status;
@@ -40,28 +39,28 @@ void *lock_forward (void *arg)
backoffs = 0; backoffs = 0;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (i == 0) { if (i == 0) {
status = pthread_mutex_lock (&mutex[i]); status = pthread_mutex_lock(&mutex[i]);
if (status != 0) if (status != 0)
err_abort (status, "First lock"); err_abort(status, "First lock");
} else { }
else {
if (backoff) if (backoff)
status = pthread_mutex_trylock (&mutex[i]); status = pthread_mutex_trylock(&mutex[i]);
else else
status = pthread_mutex_lock (&mutex[i]); status = pthread_mutex_lock(&mutex[i]);
if (status == EBUSY) { if (status == EBUSY) {
backoffs++; backoffs++;
DPRINTF (( DPRINTF((" [forward locker backing off at %d]\n", i));
" [forward locker backing off at %d]\n",
i));
for (; i >= 0; i--) { for (; i >= 0; i--) {
status = pthread_mutex_unlock (&mutex[i]); status = pthread_mutex_unlock(&mutex[i]);
if (status != 0) if (status != 0)
err_abort (status, "Backoff"); err_abort(status, "Backoff");
} }
} else { }
else {
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
DPRINTF ((" forward locker got %d\n", i)); DPRINTF((" forward locker got %d\n", i));
} }
} }
/* /*
@@ -70,20 +69,19 @@ void *lock_forward (void *arg)
*/ */
if (yield_flag) { if (yield_flag) {
if (yield_flag > 0) if (yield_flag > 0)
sched_yield (); sched_yield();
else else
sleep (1); sleep(1);
} }
} }
/* /*
* Report that we got 'em, and unlock to try again. * Report that we got 'em, and unlock to try again.
*/ */
printf ( printf("lock forward got all locks, %d backoffs\n", backoffs);
"lock forward got all locks, %d backoffs\n", backoffs); pthread_mutex_unlock(&mutex[2]);
pthread_mutex_unlock (&mutex[2]); pthread_mutex_unlock(&mutex[1]);
pthread_mutex_unlock (&mutex[1]); pthread_mutex_unlock(&mutex[0]);
pthread_mutex_unlock (&mutex[0]); sched_yield();
sched_yield ();
} }
return NULL; return NULL;
} }
@@ -93,7 +91,8 @@ void *lock_forward (void *arg)
* reverse order, to ensure a conflict with lock_forward, which * reverse order, to ensure a conflict with lock_forward, which
* does the opposite. * does the opposite.
*/ */
void *lock_backward (void *arg) void*
lock_backward(void* arg)
{ {
int i, iterate, backoffs; int i, iterate, backoffs;
int status; int status;
@@ -102,28 +101,28 @@ void *lock_backward (void *arg)
backoffs = 0; backoffs = 0;
for (i = 2; i >= 0; i--) { for (i = 2; i >= 0; i--) {
if (i == 2) { if (i == 2) {
status = pthread_mutex_lock (&mutex[i]); status = pthread_mutex_lock(&mutex[i]);
if (status != 0) if (status != 0)
err_abort (status, "First lock"); err_abort(status, "First lock");
} else { }
else {
if (backoff) if (backoff)
status = pthread_mutex_trylock (&mutex[i]); status = pthread_mutex_trylock(&mutex[i]);
else else
status = pthread_mutex_lock (&mutex[i]); status = pthread_mutex_lock(&mutex[i]);
if (status == EBUSY) { if (status == EBUSY) {
backoffs++; backoffs++;
DPRINTF (( DPRINTF((" [backward locker backing off at %d]\n", i));
" [backward locker backing off at %d]\n",
i));
for (; i < 3; i++) { for (; i < 3; i++) {
status = pthread_mutex_unlock (&mutex[i]); status = pthread_mutex_unlock(&mutex[i]);
if (status != 0) if (status != 0)
err_abort (status, "Backoff"); err_abort(status, "Backoff");
} }
} else { }
else {
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
DPRINTF ((" backward locker got %d\n", i)); DPRINTF((" backward locker got %d\n", i));
} }
} }
/* /*
@@ -132,25 +131,25 @@ void *lock_backward (void *arg)
*/ */
if (yield_flag) { if (yield_flag) {
if (yield_flag > 0) if (yield_flag > 0)
sched_yield (); sched_yield();
else else
sleep (1); sleep(1);
} }
} }
/* /*
* Report that we got 'em, and unlock to try again. * Report that we got 'em, and unlock to try again.
*/ */
printf ( printf("lock backward got all locks, %d backoffs\n", backoffs);
"lock backward got all locks, %d backoffs\n", backoffs); pthread_mutex_unlock(&mutex[0]);
pthread_mutex_unlock (&mutex[0]); pthread_mutex_unlock(&mutex[1]);
pthread_mutex_unlock (&mutex[1]); pthread_mutex_unlock(&mutex[2]);
pthread_mutex_unlock (&mutex[2]); sched_yield();
sched_yield ();
} }
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t forward, backward; pthread_t forward, backward;
int status; int status;
@@ -161,8 +160,8 @@ int main (int argc, char *argv[])
* that our threads can run concurrently, we need to * that our threads can run concurrently, we need to
* increase the concurrency level. * increase the concurrency level.
*/ */
DPRINTF (("Setting concurrency level to 2\n")); DPRINTF(("Setting concurrency level to 2\n"));
thr_setconcurrency (2); thr_setconcurrency(2);
#endif #endif
/* /*
@@ -172,7 +171,7 @@ int main (int argc, char *argv[])
* "collision." * "collision."
*/ */
if (argc > 1) if (argc > 1)
backoff = atoi (argv[1]); backoff = atoi(argv[1]);
/* /*
* If the second argument is absent, or zero, the two * If the second argument is absent, or zero, the two
@@ -186,14 +185,12 @@ int main (int argc, char *argv[])
* call sleep(1) instead. * call sleep(1) instead.
*/ */
if (argc > 2) if (argc > 2)
yield_flag = atoi (argv[2]); yield_flag = atoi(argv[2]);
status = pthread_create ( status = pthread_create(&forward, NULL, lock_forward, NULL);
&forward, NULL, lock_forward, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create forward"); err_abort(status, "Create forward");
status = pthread_create ( status = pthread_create(&backward, NULL, lock_backward, NULL);
&backward, NULL, lock_backward, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create backward"); err_abort(status, "Create backward");
pthread_exit (NULL); pthread_exit(NULL);
} }

View File

@@ -13,8 +13,7 @@ typedef struct my_struct_tag {
int value; /* Access protected by mutex */ int value; /* Access protected by mutex */
} my_struct_t; } my_struct_t;
my_struct_t data = { my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
int hibernation = 1; /* Default to 1 second */ int hibernation = 1; /* Default to 1 second */
@@ -22,26 +21,27 @@ int hibernation = 1; /* Default to 1 second */
* Thread start routine. It will set the main thread's predicate * Thread start routine. It will set the main thread's predicate
* and signal the condition variable. * and signal the condition variable.
*/ */
void * void*
wait_thread (void *arg) wait_thread(void* arg)
{ {
int status; int status;
sleep (hibernation); sleep(hibernation);
status = pthread_mutex_lock (&data.mutex); status = pthread_mutex_lock(&data.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
data.value = 1; /* Set predicate */ data.value = 1; /* Set predicate */
status = pthread_cond_signal (&data.cond); status = pthread_cond_signal(&data.cond);
if (status != 0) if (status != 0)
err_abort (status, "Signal condition"); err_abort(status, "Signal condition");
status = pthread_mutex_unlock (&data.mutex); status = pthread_mutex_unlock(&data.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int status; int status;
pthread_t wait_thread_id; pthread_t wait_thread_id;
@@ -54,14 +54,14 @@ int main (int argc, char *argv[])
* condition wait below time out or wake normally. * condition wait below time out or wake normally.
*/ */
if (argc > 1) if (argc > 1)
hibernation = atoi (argv[1]); hibernation = atoi(argv[1]);
/* /*
* Create wait_thread. * Create wait_thread.
*/ */
status = pthread_create (&wait_thread_id, NULL, wait_thread, NULL); status = pthread_create(&wait_thread_id, NULL, wait_thread, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create wait thread"); err_abort(status, "Create wait thread");
/* /*
* Wait on the condition variable for 2 seconds, or until * Wait on the condition variable for 2 seconds, or until
@@ -69,27 +69,26 @@ int main (int argc, char *argv[])
* should signal. If you raise "hibernation" above 2 * should signal. If you raise "hibernation" above 2
* seconds, it will time out. * seconds, it will time out.
*/ */
timeout.tv_sec = time (NULL) + 2; timeout.tv_sec = time(NULL) + 2;
timeout.tv_nsec = 0; timeout.tv_nsec = 0;
status = pthread_mutex_lock (&data.mutex); status = pthread_mutex_lock(&data.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
while (data.value == 0) { while (data.value == 0) {
status = pthread_cond_timedwait ( status = pthread_cond_timedwait(&data.cond, &data.mutex, &timeout);
&data.cond, &data.mutex, &timeout);
if (status == ETIMEDOUT) { if (status == ETIMEDOUT) {
printf ("Condition wait timed out.\n"); printf("Condition wait timed out.\n");
break; break;
} }
else if (status != 0) else if (status != 0)
err_abort (status, "Wait on condition"); err_abort(status, "Wait on condition");
} }
if (data.value != 0) if (data.value != 0)
printf ("Condition was signaled.\n"); printf("Condition was signaled.\n");
status = pthread_mutex_unlock (&data.mutex); status = pthread_mutex_unlock(&data.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
return 0; return 0;
} }

View File

@@ -15,26 +15,27 @@ typedef struct my_struct_tag {
int value; /* Access protected by mutex */ int value; /* Access protected by mutex */
} my_struct_t; } my_struct_t;
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
my_struct_t *data; my_struct_t* data;
int status; int status;
data = malloc (sizeof (my_struct_t)); data = malloc(sizeof(my_struct_t));
if (data == NULL) if (data == NULL)
errno_abort ("Allocate structure"); errno_abort("Allocate structure");
status = pthread_mutex_init (&data->mutex, NULL); status = pthread_mutex_init(&data->mutex, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init mutex"); err_abort(status, "Init mutex");
status = pthread_cond_init (&data->cond, NULL); status = pthread_cond_init(&data->cond, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init condition"); err_abort(status, "Init condition");
status = pthread_cond_destroy (&data->cond); status = pthread_cond_destroy(&data->cond);
if (status != 0) if (status != 0)
err_abort (status, "Destroy condition"); err_abort(status, "Destroy condition");
status = pthread_mutex_destroy (&data->mutex); status = pthread_mutex_destroy(&data->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Destroy mutex"); err_abort(status, "Destroy mutex");
(void)free (data); (void) free(data);
return status; return status;
} }

View File

@@ -18,10 +18,10 @@ typedef struct my_struct_tag {
int value; /* Access protected by mutex */ int value; /* Access protected by mutex */
} my_struct_t; } my_struct_t;
my_struct_t data = { my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
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

@@ -14,20 +14,21 @@ typedef struct my_struct_tag {
int value; /* Access protected by mutex */ int value; /* Access protected by mutex */
} my_struct_t; } my_struct_t;
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
my_struct_t *data; my_struct_t* data;
int status; int status;
data = malloc (sizeof (my_struct_t)); data = malloc(sizeof(my_struct_t));
if (data == NULL) if (data == NULL)
errno_abort ("Allocate structure"); errno_abort("Allocate structure");
status = pthread_mutex_init (&data->mutex, NULL); status = pthread_mutex_init(&data->mutex, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init mutex"); err_abort(status, "Init mutex");
status = pthread_mutex_destroy (&data->mutex); status = pthread_mutex_destroy(&data->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Destroy mutex"); err_abort(status, "Destroy mutex");
(void)free (data); (void) free(data);
return status; return status;
} }

View File

@@ -17,7 +17,8 @@ typedef struct my_struct_tag {
my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, 0}; 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 * Thread start routine that repeatedly locks a mutex and
* increments a counter. * increments a counter.
*/ */
void *counter_thread(void *arg) { void*
counter_thread(void* arg)
{
int status; int status;
int spin; int spin;
@@ -36,11 +38,13 @@ void *counter_thread(void *arg) {
*/ */
while (time(NULL) < end_time) { while (time(NULL) < end_time) {
status = pthread_mutex_lock(&mutex); 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++; for (spin = 0; spin < SPIN; spin++) counter++;
sleep(4); sleep(4);
status = pthread_mutex_unlock(&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) err_abort(status, "Unlock mutex"); if (status != 0)
err_abort(status, "Unlock mutex");
sleep(1); sleep(1);
} }
printf("Counter is %#lx\n", counter); 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 * seconds, try to lock the mutex and read the counter. If the
* trylock fails, skip this cycle. * trylock fails, skip this cycle.
*/ */
void *monitor_thread(void *arg) { void*
monitor_thread(void* arg)
{
int status; int status;
int misses = 0; int misses = 0;
@@ -64,18 +70,23 @@ void *monitor_thread(void *arg) {
sleep(3); sleep(3);
status = pthread_mutex_trylock(&mutex); status = pthread_mutex_trylock(&mutex);
if (status != EBUSY) { 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); printf("Counter is %ld\n", counter / SPIN);
status = pthread_mutex_unlock(&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) err_abort(status, "Unlock mutex"); if (status != 0)
} else err_abort(status, "Unlock mutex");
}
else
misses++; /* Count "misses" on the lock */ misses++; /* Count "misses" on the lock */
} }
printf("Monitor thread missed update %d times.\n", misses); printf("Monitor thread missed update %d times.\n", misses);
return NULL; return NULL;
} }
int main(int argc, char *argv[]) { int
main(int argc, char* argv[])
{
int status; int status;
pthread_t counter_thread_id; pthread_t counter_thread_id;
pthread_t monitor_thread_id; pthread_t monitor_thread_id;
@@ -92,12 +103,16 @@ int main(int argc, char *argv[]) {
end_time = time(NULL) + 60; /* Run for 1 minute */ end_time = time(NULL) + 60; /* Run for 1 minute */
status = pthread_create(&counter_thread_id, NULL, counter_thread, NULL); status = pthread_create(&counter_thread_id, NULL, counter_thread, NULL);
if (status != 0) err_abort(status, "Create counter thread"); if (status != 0)
err_abort(status, "Create counter thread");
status = pthread_create(&monitor_thread_id, NULL, monitor_thread, NULL); 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); 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); 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; return 0;
} }

View File

@@ -9,10 +9,10 @@
* by calling thr_setconcurrency(), because threads are not * by calling thr_setconcurrency(), because threads are not
* timesliced. * timesliced.
*/ */
#include <sys/types.h> #include <dirent.h>
#include <pthread.h> #include <pthread.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <dirent.h> #include <sys/types.h>
#include "errors.h" #include "errors.h"
#define CREW_SIZE 4 #define CREW_SIZE 4
@@ -22,9 +22,9 @@
* crew_start, and each worker may queue additional items. * crew_start, and each worker may queue additional items.
*/ */
typedef struct work_tag { typedef struct work_tag {
struct work_tag *next; /* Next work item */ struct work_tag* next; /* Next work item */
char *path; /* Directory or file */ char* path; /* Directory or file */
char *string; /* Search string */ char* string; /* Search string */
} work_t, *work_p; } work_t, *work_p;
/* /*
@@ -34,7 +34,7 @@ typedef struct work_tag {
typedef struct worker_tag { typedef struct worker_tag {
int index; /* Thread's index */ int index; /* Thread's index */
pthread_t thread; /* Thread for stage */ pthread_t thread; /* Thread for stage */
struct crew_tag *crew; /* Pointer to crew */ struct crew_tag* crew; /* Pointer to crew */
} worker_t, *worker_p; } worker_t, *worker_p;
/* /*
@@ -43,7 +43,7 @@ typedef struct worker_tag {
*/ */
typedef struct crew_tag { typedef struct crew_tag {
int crew_size; /* Size of array */ int crew_size; /* Size of array */
worker_t crew[CREW_SIZE];/* Crew members */ worker_t crew[CREW_SIZE]; /* Crew members */
long work_count; /* Count of work items */ long work_count; /* Count of work items */
work_t *first, *last; /* First & last work item */ work_t *first, *last; /* First & last work item */
pthread_mutex_t mutex; /* Mutex for crew data */ pthread_mutex_t mutex; /* Mutex for crew data */
@@ -58,13 +58,14 @@ size_t name_max; /* Name length */
* The thread start routine for crew threads. Waits until "go" * The thread start routine for crew threads. Waits until "go"
* command, processes work items until requested to shut down. * command, processes work items until requested to shut down.
*/ */
void *worker_routine (void *arg) void*
worker_routine(void* arg)
{ {
worker_p mine = (worker_t*)arg; worker_p mine = (worker_t*) arg;
crew_p crew = mine->crew; crew_p crew = mine->crew;
work_p work, new_work; work_p work, new_work;
struct stat filestat; struct stat filestat;
struct dirent *entry; struct dirent* entry;
int status; int status;
/* /*
@@ -73,30 +74,29 @@ void *worker_routine (void *arg)
* buffer. Thus, allocate a "big chunk" of memory, and use * buffer. Thus, allocate a "big chunk" of memory, and use
* it as a buffer. * it as a buffer.
*/ */
entry = (struct dirent*)malloc ( entry = (struct dirent*) malloc(sizeof(struct dirent) + name_max);
sizeof (struct dirent) + name_max);
if (entry == NULL) if (entry == NULL)
errno_abort ("Allocating dirent"); errno_abort("Allocating dirent");
status = pthread_mutex_lock (&crew->mutex); status = pthread_mutex_lock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock crew mutex"); err_abort(status, "Lock crew mutex");
/* /*
* There won't be any work when the crew is created, so wait * There won't be any work when the crew is created, so wait
* until something's put on the queue. * until something's put on the queue.
*/ */
while (crew->work_count == 0) { while (crew->work_count == 0) {
status = pthread_cond_wait (&crew->go, &crew->mutex); status = pthread_cond_wait(&crew->go, &crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait for go"); err_abort(status, "Wait for go");
} }
status = pthread_mutex_unlock (&crew->mutex); status = pthread_mutex_unlock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
DPRINTF (("Crew %d starting\n", mine->index)); DPRINTF(("Crew %d starting\n", mine->index));
/* /*
* Now, as long as there's work, keep doing it. * Now, as long as there's work, keep doing it.
@@ -108,20 +108,24 @@ void *worker_routine (void *arg)
* crew->first is NULL, there's no work. But if * crew->first is NULL, there's no work. But if
* crew->work_count goes to zero, we're done. * crew->work_count goes to zero, we're done.
*/ */
status = pthread_mutex_lock (&crew->mutex); status = pthread_mutex_lock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock crew mutex"); err_abort(status, "Lock crew mutex");
DPRINTF (("Crew %d top: first is %#lx, count is %d\n", DPRINTF(("Crew %d top: first is %#lx, count is %d\n",
mine->index, crew->first, crew->work_count)); mine->index,
crew->first,
crew->work_count));
while (crew->first == NULL) { while (crew->first == NULL) {
status = pthread_cond_wait (&crew->go, &crew->mutex); status = pthread_cond_wait(&crew->go, &crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait for work"); err_abort(status, "Wait for work");
} }
DPRINTF (("Crew %d woke: %#lx, %d\n", DPRINTF(("Crew %d woke: %#lx, %d\n",
mine->index, crew->first, crew->work_count)); mine->index,
crew->first,
crew->work_count));
/* /*
* Remove and process a work item * Remove and process a work item
@@ -131,49 +135,50 @@ void *worker_routine (void *arg)
if (crew->first == NULL) if (crew->first == NULL)
crew->last = NULL; crew->last = NULL;
DPRINTF (("Crew %d took %#lx, leaves first %#lx, last %#lx\n", DPRINTF(("Crew %d took %#lx, leaves first %#lx, last %#lx\n",
mine->index, work, crew->first, crew->last)); mine->index,
work,
crew->first,
crew->last));
status = pthread_mutex_unlock (&crew->mutex); status = pthread_mutex_unlock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
/* /*
* We have a work item. Process it, which may involve * We have a work item. Process it, which may involve
* queuing new work items. * queuing new work items.
*/ */
status = lstat (work->path, &filestat); status = lstat(work->path, &filestat);
if (S_ISLNK (filestat.st_mode)) if (S_ISLNK(filestat.st_mode))
printf ( printf("Thread %d: %s is a link, skipping.\n", mine->index, work->path);
"Thread %d: %s is a link, skipping.\n", else if (S_ISDIR(filestat.st_mode)) {
mine->index, DIR* directory;
work->path); struct dirent* result;
else if (S_ISDIR (filestat.st_mode)) {
DIR *directory;
struct dirent *result;
/* /*
* If the file is a directory, search it and place * If the file is a directory, search it and place
* all files onto the queue as new work items. * all files onto the queue as new work items.
*/ */
directory = opendir (work->path); directory = opendir(work->path);
if (directory == NULL) { if (directory == NULL) {
fprintf ( fprintf(stderr,
stderr, "Unable to open directory %s: %d (%s)\n", "Unable to open directory %s: %d (%s)\n",
work->path, work->path,
errno, strerror (errno)); errno,
strerror(errno));
continue; continue;
} }
while (1) { while (1) {
status = readdir_r (directory, entry, &result); status = readdir_r(directory, entry, &result);
if (status != 0) { if (status != 0) {
fprintf ( fprintf(stderr,
stderr,
"Unable to read directory %s: %d (%s)\n", "Unable to read directory %s: %d (%s)\n",
work->path, work->path,
status, strerror (status)); status,
strerror(status));
break; break;
} }
if (result == NULL) if (result == NULL)
@@ -182,104 +187,111 @@ void *worker_routine (void *arg)
/* /*
* Ignore "." and ".." entries. * Ignore "." and ".." entries.
*/ */
if (strcmp (entry->d_name, ".") == 0) if (strcmp(entry->d_name, ".") == 0)
continue; continue;
if (strcmp (entry->d_name, "..") == 0) if (strcmp(entry->d_name, "..") == 0)
continue; continue;
new_work = (work_p)malloc (sizeof (work_t)); new_work = (work_p) malloc(sizeof(work_t));
if (new_work == NULL) if (new_work == NULL)
errno_abort ("Unable to allocate space"); errno_abort("Unable to allocate space");
new_work->path = (char*)malloc (path_max); new_work->path = (char*) malloc(path_max);
if (new_work->path == NULL) if (new_work->path == NULL)
errno_abort ("Unable to allocate path"); errno_abort("Unable to allocate path");
strcpy (new_work->path, work->path); strcpy(new_work->path, work->path);
strcat (new_work->path, "/"); strcat(new_work->path, "/");
strcat (new_work->path, entry->d_name); strcat(new_work->path, entry->d_name);
new_work->string = work->string; new_work->string = work->string;
new_work->next = NULL; new_work->next = NULL;
status = pthread_mutex_lock (&crew->mutex); status = pthread_mutex_lock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
if (crew->first == NULL) { if (crew->first == NULL) {
crew->first = new_work; crew->first = new_work;
crew->last = new_work; crew->last = new_work;
} else { }
else {
crew->last->next = new_work; crew->last->next = new_work;
crew->last = new_work; crew->last = new_work;
} }
crew->work_count++; crew->work_count++;
DPRINTF (( DPRINTF(("Crew %d: add work %#lx, first %#lx, last %#lx, %d\n",
"Crew %d: add work %#lx, first %#lx, last %#lx, %d\n", mine->index,
mine->index, new_work, crew->first, new_work,
crew->last, crew->work_count)); crew->first,
status = pthread_cond_signal (&crew->go); crew->last,
status = pthread_mutex_unlock (&crew->mutex); crew->work_count));
status = pthread_cond_signal(&crew->go);
status = pthread_mutex_unlock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
} }
closedir (directory); closedir(directory);
} else if (S_ISREG (filestat.st_mode)) { }
FILE *search; else if (S_ISREG(filestat.st_mode)) {
FILE* search;
char buffer[256], *bufptr, *search_ptr; char buffer[256], *bufptr, *search_ptr;
/* /*
* If this is a file, not a directory, then search * If this is a file, not a directory, then search
* it for the string. * it for the string.
*/ */
search = fopen (work->path, "r"); search = fopen(work->path, "r");
if (search == NULL) if (search == NULL)
fprintf ( fprintf(stderr,
stderr, "Unable to open %s: %d (%s)\n", "Unable to open %s: %d (%s)\n",
work->path, work->path,
errno, strerror (errno)); errno,
strerror(errno));
else { else {
while (1) { while (1) {
bufptr = fgets ( bufptr = fgets(buffer, sizeof(buffer), search);
buffer, sizeof (buffer), search);
if (bufptr == NULL) { if (bufptr == NULL) {
if (feof (search)) if (feof(search))
break; break;
if (ferror (search)) { if (ferror(search)) {
fprintf ( fprintf(stderr,
stderr,
"Unable to read %s: %d (%s)\n", "Unable to read %s: %d (%s)\n",
work->path, work->path,
errno, strerror (errno)); errno,
strerror(errno));
break; break;
} }
} }
search_ptr = strstr (buffer, work->string); search_ptr = strstr(buffer, work->string);
if (search_ptr != NULL) { if (search_ptr != NULL) {
flockfile (stdout); flockfile(stdout);
printf ( printf("Thread %d found \"%s\" in %s\n",
"Thread %d found \"%s\" in %s\n", mine->index,
mine->index, work->string, work->path); work->string,
work->path);
#if 0 #if 0
printf ("%s\n", buffer); printf ("%s\n", buffer);
#endif #endif
funlockfile (stdout); funlockfile(stdout);
break; break;
} }
} }
fclose (search); fclose(search);
} }
} else }
fprintf ( else
stderr, fprintf(stderr,
"Thread %d: %s is type %o (%s))\n", "Thread %d: %s is type %o (%s))\n",
mine->index, mine->index,
work->path, work->path,
filestat.st_mode & S_IFMT, filestat.st_mode & S_IFMT,
(S_ISFIFO (filestat.st_mode) ? "FIFO" (S_ISFIFO(filestat.st_mode)
: (S_ISCHR (filestat.st_mode) ? "CHR" ? "FIFO"
: (S_ISBLK (filestat.st_mode) ? "BLK" : (S_ISCHR(filestat.st_mode)
: (S_ISSOCK (filestat.st_mode) ? "SOCK" ? "CHR"
: (S_ISBLK(filestat.st_mode)
? "BLK"
: (S_ISSOCK(filestat.st_mode) ? "SOCK"
: "unknown"))))); : "unknown")))));
free (work->path); /* Free path buffer */ free(work->path); /* Free path buffer */
free (work); /* We're done with this */ free(work); /* We're done with this */
/* /*
* Decrement count of outstanding work items, and wake * Decrement count of outstanding work items, and wake
@@ -290,38 +302,38 @@ void *worker_routine (void *arg)
* processing the current work item. That ensures the * processing the current work item. That ensures the
* count won't go to 0 until we're really done. * count won't go to 0 until we're really done.
*/ */
status = pthread_mutex_lock (&crew->mutex); status = pthread_mutex_lock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock crew mutex"); err_abort(status, "Lock crew mutex");
crew->work_count--; crew->work_count--;
DPRINTF (("Crew %d decremented work to %d\n", mine->index, DPRINTF(
crew->work_count)); ("Crew %d decremented work to %d\n", mine->index, crew->work_count));
if (crew->work_count <= 0) { if (crew->work_count <= 0) {
DPRINTF (("Crew thread %d done\n", mine->index)); DPRINTF(("Crew thread %d done\n", mine->index));
status = pthread_cond_broadcast (&crew->done); status = pthread_cond_broadcast(&crew->done);
if (status != 0) if (status != 0)
err_abort (status, "Wake waiters"); err_abort(status, "Wake waiters");
status = pthread_mutex_unlock (&crew->mutex); status = pthread_mutex_unlock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
break; break;
} }
status = pthread_mutex_unlock (&crew->mutex); status = pthread_mutex_unlock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
} }
free (entry); free(entry);
return NULL; return NULL;
} }
/* /*
* Create a work crew. * Create a work crew.
*/ */
int crew_create (crew_t *crew, int crew_size) int
crew_create(crew_t* crew, int crew_size)
{ {
int crew_index; int crew_index;
int status; int status;
@@ -340,13 +352,13 @@ int crew_create (crew_t *crew, int crew_size)
/* /*
* Initialize synchronization objects * Initialize synchronization objects
*/ */
status = pthread_mutex_init (&crew->mutex, NULL); status = pthread_mutex_init(&crew->mutex, NULL);
if (status != 0) if (status != 0)
return status; return status;
status = pthread_cond_init (&crew->done, NULL); status = pthread_cond_init(&crew->done, NULL);
if (status != 0) if (status != 0)
return status; return status;
status = pthread_cond_init (&crew->go, NULL); status = pthread_cond_init(&crew->go, NULL);
if (status != 0) if (status != 0)
return status; return status;
@@ -356,10 +368,12 @@ int crew_create (crew_t *crew, int crew_size)
for (crew_index = 0; crew_index < CREW_SIZE; crew_index++) { for (crew_index = 0; crew_index < CREW_SIZE; crew_index++) {
crew->crew[crew_index].index = crew_index; crew->crew[crew_index].index = crew_index;
crew->crew[crew_index].crew = crew; crew->crew[crew_index].crew = crew;
status = pthread_create (&crew->crew[crew_index].thread, status = pthread_create(&crew->crew[crew_index].thread,
NULL, worker_routine, (void*)&crew->crew[crew_index]); NULL,
worker_routine,
(void*) &crew->crew[crew_index]);
if (status != 0) if (status != 0)
err_abort (status, "Create worker"); err_abort(status, "Create worker");
} }
return 0; return 0;
} }
@@ -368,15 +382,13 @@ int crew_create (crew_t *crew, int crew_size)
* Pass a file path to a work crew previously created * Pass a file path to a work crew previously created
* using crew_create * using crew_create
*/ */
int crew_start ( int
crew_p crew, crew_start(crew_p crew, char* filepath, char* search)
char *filepath,
char *search)
{ {
work_p request; work_p request;
int status; int status;
status = pthread_mutex_lock (&crew->mutex); status = pthread_mutex_lock(&crew->mutex);
if (status != 0) if (status != 0)
return status; return status;
@@ -384,83 +396,86 @@ int crew_start (
* If the crew is busy, wait for them to finish. * If the crew is busy, wait for them to finish.
*/ */
while (crew->work_count > 0) { while (crew->work_count > 0) {
status = pthread_cond_wait (&crew->done, &crew->mutex); status = pthread_cond_wait(&crew->done, &crew->mutex);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&crew->mutex); pthread_mutex_unlock(&crew->mutex);
return status; return status;
} }
} }
errno = 0; errno = 0;
path_max = pathconf (filepath, _PC_PATH_MAX); path_max = pathconf(filepath, _PC_PATH_MAX);
if (path_max == -1) { if (path_max == -1) {
if (errno == 0) if (errno == 0)
path_max = 1024; /* "No limit" */ path_max = 1024; /* "No limit" */
else else
errno_abort ("Unable to get PATH_MAX"); errno_abort("Unable to get PATH_MAX");
} }
errno = 0; errno = 0;
name_max = pathconf (filepath, _PC_NAME_MAX); name_max = pathconf(filepath, _PC_NAME_MAX);
if (name_max == -1) { if (name_max == -1) {
if (errno == 0) if (errno == 0)
name_max = 256; /* "No limit" */ name_max = 256; /* "No limit" */
else else
errno_abort ("Unable to get NAME_MAX"); errno_abort("Unable to get NAME_MAX");
} }
DPRINTF (( DPRINTF(("PATH_MAX for %s is %ld, NAME_MAX is %ld\n",
"PATH_MAX for %s is %ld, NAME_MAX is %ld\n", filepath,
filepath, path_max, name_max)); path_max,
name_max));
path_max++; /* Add null byte */ path_max++; /* Add null byte */
name_max++; /* Add null byte */ name_max++; /* Add null byte */
request = (work_p)malloc (sizeof (work_t)); request = (work_p) malloc(sizeof(work_t));
if (request == NULL) if (request == NULL)
errno_abort ("Unable to allocate request"); errno_abort("Unable to allocate request");
DPRINTF (("Requesting %s\n", filepath)); DPRINTF(("Requesting %s\n", filepath));
request->path = (char*)malloc (path_max); request->path = (char*) malloc(path_max);
if (request->path == NULL) if (request->path == NULL)
errno_abort ("Unable to allocate path"); errno_abort("Unable to allocate path");
strcpy (request->path, filepath); strcpy(request->path, filepath);
request->string = search; request->string = search;
request->next = NULL; request->next = NULL;
if (crew->first == NULL) { if (crew->first == NULL) {
crew->first = request; crew->first = request;
crew->last = request; crew->last = request;
} else { }
else {
crew->last->next = request; crew->last->next = request;
crew->last = request; crew->last = request;
} }
crew->work_count++; crew->work_count++;
status = pthread_cond_signal (&crew->go); status = pthread_cond_signal(&crew->go);
if (status != 0) { if (status != 0) {
free (crew->first); free(crew->first);
crew->first = NULL; crew->first = NULL;
crew->work_count = 0; crew->work_count = 0;
pthread_mutex_unlock (&crew->mutex); pthread_mutex_unlock(&crew->mutex);
return status; return status;
} }
while (crew->work_count > 0) { while (crew->work_count > 0) {
status = pthread_cond_wait (&crew->done, &crew->mutex); status = pthread_cond_wait(&crew->done, &crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "waiting for crew to finish"); err_abort(status, "waiting for crew to finish");
} }
status = pthread_mutex_unlock (&crew->mutex); status = pthread_mutex_unlock(&crew->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock crew mutex"); err_abort(status, "Unlock crew mutex");
return 0; return 0;
} }
/* /*
* The main program to "drive" the crew... * The main program to "drive" the crew...
*/ */
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
crew_t my_crew; crew_t my_crew;
char line[128], *next; char line[128], *next;
int status; int status;
if (argc < 3) { if (argc < 3) {
fprintf (stderr, "Usage: %s string path\n", argv[0]); fprintf(stderr, "Usage: %s string path\n", argv[0]);
return -1; return -1;
} }
@@ -470,16 +485,16 @@ int main (int argc, char *argv[])
* that our threads can run concurrently, we need to * that our threads can run concurrently, we need to
* increase the concurrency level to CREW_SIZE. * increase the concurrency level to CREW_SIZE.
*/ */
DPRINTF (("Setting concurrency level to %d\n", CREW_SIZE)); DPRINTF(("Setting concurrency level to %d\n", CREW_SIZE));
thr_setconcurrency (CREW_SIZE); thr_setconcurrency(CREW_SIZE);
#endif #endif
status = crew_create (&my_crew, CREW_SIZE); status = crew_create(&my_crew, CREW_SIZE);
if (status != 0) if (status != 0)
err_abort (status, "Create crew"); err_abort(status, "Create crew");
status = crew_start (&my_crew, argv[2], argv[1]); status = crew_start(&my_crew, argv[2], argv[1]);
if (status != 0) if (status != 0)
err_abort (status, "Start crew"); err_abort(status, "Start crew");
return 0; return 0;
} }

View File

@@ -22,7 +22,7 @@ typedef struct stage_tag {
int data_ready; /* Data present */ int data_ready; /* Data present */
long data; /* Data to process */ long data; /* Data to process */
pthread_t thread; /* Thread for stage */ pthread_t thread; /* Thread for stage */
struct stage_tag *next; /* Next stage */ struct stage_tag* next; /* Next stage */
} stage_t; } stage_t;
/* /*
@@ -31,8 +31,8 @@ typedef struct stage_tag {
*/ */
typedef struct pipe_tag { typedef struct pipe_tag {
pthread_mutex_t mutex; /* Mutex to protect pipe */ pthread_mutex_t mutex; /* Mutex to protect pipe */
stage_t *head; /* First stage */ stage_t* head; /* First stage */
stage_t *tail; /* Final stage */ stage_t* tail; /* Final stage */
int stages; /* Number of stages */ int stages; /* Number of stages */
int active; /* Active data elements */ int active; /* Active data elements */
} pipe_t; } pipe_t;
@@ -42,11 +42,12 @@ typedef struct pipe_tag {
* specified pipe stage. Threads use this to pass * specified pipe stage. Threads use this to pass
* along the modified data item. * along the modified data item.
*/ */
int pipe_send (stage_t *stage, long data) int
pipe_send(stage_t* stage, long data)
{ {
int status; int status;
status = pthread_mutex_lock (&stage->mutex); status = pthread_mutex_lock(&stage->mutex);
if (status != 0) if (status != 0)
return status; return status;
/* /*
@@ -54,9 +55,9 @@ int pipe_send (stage_t *stage, long data)
* to be consumed. * to be consumed.
*/ */
while (stage->data_ready) { while (stage->data_ready) {
status = pthread_cond_wait (&stage->ready, &stage->mutex); status = pthread_cond_wait(&stage->ready, &stage->mutex);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&stage->mutex); pthread_mutex_unlock(&stage->mutex);
return status; return status;
} }
} }
@@ -66,12 +67,12 @@ int pipe_send (stage_t *stage, long data)
*/ */
stage->data = data; stage->data = data;
stage->data_ready = 1; stage->data_ready = 1;
status = pthread_cond_signal (&stage->avail); status = pthread_cond_signal(&stage->avail);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&stage->mutex); pthread_mutex_unlock(&stage->mutex);
return status; return status;
} }
status = pthread_mutex_unlock (&stage->mutex); status = pthread_mutex_unlock(&stage->mutex);
return status; return status;
} }
@@ -81,26 +82,27 @@ int pipe_send (stage_t *stage, long data)
* caller or the previous stage, modify the data * caller or the previous stage, modify the data
* and pass it along to the next (or final) stage. * and pass it along to the next (or final) stage.
*/ */
void *pipe_stage (void *arg) void*
pipe_stage(void* arg)
{ {
stage_t *stage = (stage_t*)arg; stage_t* stage = (stage_t*) arg;
stage_t *next_stage = stage->next; stage_t* next_stage = stage->next;
int status; int status;
status = pthread_mutex_lock (&stage->mutex); status = pthread_mutex_lock(&stage->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock pipe stage"); err_abort(status, "Lock pipe stage");
while (1) { while (1) {
while (stage->data_ready != 1) { while (stage->data_ready != 1) {
status = pthread_cond_wait (&stage->avail, &stage->mutex); status = pthread_cond_wait(&stage->avail, &stage->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait for previous stage"); err_abort(status, "Wait for previous stage");
} }
pipe_send (next_stage, stage->data + 1); pipe_send(next_stage, stage->data + 1);
stage->data_ready = 0; stage->data_ready = 0;
status = pthread_cond_signal (&stage->ready); status = pthread_cond_signal(&stage->ready);
if (status != 0) if (status != 0)
err_abort (status, "Wake next stage"); err_abort(status, "Wake next stage");
} }
/* /*
* Notice that the routine never unlocks the stage->mutex. * Notice that the routine never unlocks the stage->mutex.
@@ -116,37 +118,38 @@ void *pipe_stage (void *arg)
* data is initialized and the threads created. They'll * data is initialized and the threads created. They'll
* wait for data. * wait for data.
*/ */
int pipe_create (pipe_t *pipe, int stages) int
pipe_create(pipe_t* pipe, int stages)
{ {
int pipe_index; int pipe_index;
stage_t **link = &pipe->head, *new_stage, *stage; stage_t **link = &pipe->head, *new_stage, *stage;
int status; int status;
status = pthread_mutex_init (&pipe->mutex, NULL); status = pthread_mutex_init(&pipe->mutex, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init pipe mutex"); err_abort(status, "Init pipe mutex");
pipe->stages = stages; pipe->stages = stages;
pipe->active = 0; pipe->active = 0;
for (pipe_index = 0; pipe_index <= stages; pipe_index++) { for (pipe_index = 0; pipe_index <= stages; pipe_index++) {
new_stage = (stage_t*)malloc (sizeof (stage_t)); new_stage = (stage_t*) malloc(sizeof(stage_t));
if (new_stage == NULL) if (new_stage == NULL)
errno_abort ("Allocate stage"); errno_abort("Allocate stage");
status = pthread_mutex_init (&new_stage->mutex, NULL); status = pthread_mutex_init(&new_stage->mutex, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init stage mutex"); err_abort(status, "Init stage mutex");
status = pthread_cond_init (&new_stage->avail, NULL); status = pthread_cond_init(&new_stage->avail, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init avail condition"); err_abort(status, "Init avail condition");
status = pthread_cond_init (&new_stage->ready, NULL); status = pthread_cond_init(&new_stage->ready, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init ready condition"); err_abort(status, "Init ready condition");
new_stage->data_ready = 0; new_stage->data_ready = 0;
*link = new_stage; *link = new_stage;
link = &new_stage->next; link = &new_stage->next;
} }
*link = (stage_t*)NULL; /* Terminate list */ *link = (stage_t*) NULL; /* Terminate list */
pipe->tail = new_stage; /* Record the tail */ pipe->tail = new_stage; /* Record the tail */
/* /*
@@ -162,13 +165,10 @@ int pipe_create (pipe_t *pipe, int stages)
* memory cleanup done for earlier errors, it will simply * memory cleanup done for earlier errors, it will simply
* abort. * abort.
*/ */
for ( stage = pipe->head; for (stage = pipe->head; stage->next != NULL; stage = stage->next) {
stage->next != NULL; status = pthread_create(&stage->thread, NULL, pipe_stage, (void*) stage);
stage = stage->next) {
status = pthread_create (
&stage->thread, NULL, pipe_stage, (void*)stage);
if (status != 0) if (status != 0)
err_abort (status, "Create pipe stage"); err_abort(status, "Create pipe stage");
} }
return 0; return 0;
} }
@@ -181,18 +181,19 @@ int pipe_create (pipe_t *pipe, int stages)
* (note that the pipe will stall when each stage fills, * (note that the pipe will stall when each stage fills,
* until the result is collected). * until the result is collected).
*/ */
int pipe_start (pipe_t *pipe, long value) int
pipe_start(pipe_t* pipe, long value)
{ {
int status; int status;
status = pthread_mutex_lock (&pipe->mutex); status = pthread_mutex_lock(&pipe->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock pipe mutex"); err_abort(status, "Lock pipe mutex");
pipe->active++; pipe->active++;
status = pthread_mutex_unlock (&pipe->mutex); status = pthread_mutex_unlock(&pipe->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock pipe mutex"); err_abort(status, "Unlock pipe mutex");
pipe_send (pipe->head, value); pipe_send(pipe->head, value);
return 0; return 0;
} }
@@ -200,64 +201,68 @@ int pipe_start (pipe_t *pipe, long value)
* Collect the result of the pipeline. Wait for a * Collect the result of the pipeline. Wait for a
* result if the pipeline hasn't produced one. * result if the pipeline hasn't produced one.
*/ */
int pipe_result (pipe_t *pipe, long *result) int
pipe_result(pipe_t* pipe, long* result)
{ {
stage_t *tail = pipe->tail; stage_t* tail = pipe->tail;
long value; long value;
int empty = 0; int empty = 0;
int status; int status;
status = pthread_mutex_lock (&pipe->mutex); status = pthread_mutex_lock(&pipe->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock pipe mutex"); err_abort(status, "Lock pipe mutex");
if (pipe->active <= 0) if (pipe->active <= 0)
empty = 1; empty = 1;
else else
pipe->active--; pipe->active--;
status = pthread_mutex_unlock (&pipe->mutex); status = pthread_mutex_unlock(&pipe->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock pipe mutex"); err_abort(status, "Unlock pipe mutex");
if (empty) if (empty)
return 0; return 0;
pthread_mutex_lock (&tail->mutex); pthread_mutex_lock(&tail->mutex);
while (!tail->data_ready) while (!tail->data_ready) pthread_cond_wait(&tail->avail, &tail->mutex);
pthread_cond_wait (&tail->avail, &tail->mutex);
*result = tail->data; *result = tail->data;
tail->data_ready = 0; tail->data_ready = 0;
pthread_cond_signal (&tail->ready); pthread_cond_signal(&tail->ready);
pthread_mutex_unlock (&tail->mutex); pthread_mutex_unlock(&tail->mutex);
return 1; return 1;
} }
/* /*
* The main program to "drive" the pipeline... * The main program to "drive" the pipeline...
*/ */
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pipe_t my_pipe; pipe_t my_pipe;
long value, result; long value, result;
int status; int status;
char line[128]; char line[128];
pipe_create (&my_pipe, 10); pipe_create(&my_pipe, 10);
printf ("Enter integer values, or \"=\" for next result\n"); printf("Enter integer values, or \"=\" for next result\n");
while (1) { while (1) {
printf ("Data> "); printf("Data> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0); if (fgets(line, sizeof(line), stdin) == NULL)
if (strlen (line) <= 1) continue; exit(0);
if (strlen (line) <= 2 && line[0] == '=') { if (strlen(line) <= 1)
if (pipe_result (&my_pipe, &result)) continue;
printf ("Result is %ld\n", result); if (strlen(line) <= 2 && line[0] == '=') {
if (pipe_result(&my_pipe, &result))
printf("Result is %ld\n", result);
else else
printf ("Pipe is empty\n"); printf("Pipe is empty\n");
} else { }
if (sscanf (line, "%ld", &value) < 1) else {
fprintf (stderr, "Enter an integer value\n"); if (sscanf(line, "%ld", &value) < 1)
fprintf(stderr, "Enter an integer value\n");
else else
pipe_start (&my_pipe, value); pipe_start(&my_pipe, value);
} }
} }
} }

View File

@@ -26,7 +26,7 @@ struct stage_tag {
bool isDataAvail; /* Data present */ bool isDataAvail; /* Data present */
long data; /* Data to process */ long data; /* Data to process */
pthread_t thread; /* Thread for stage */ pthread_t thread; /* Thread for stage */
stage_tag *next; stage_tag* next;
}; };
using stage_t = stage_tag; using stage_t = stage_tag;
@@ -50,11 +50,14 @@ using pipe_t = pipe_tag;
* specified pipe stage. Threads use this to pass * specified pipe stage. Threads use this to pass
* along the modified data item. * along the modified data item.
*/ */
int pipe_send(stage_t &stage, long data) { int
pipe_send(stage_t& stage, long data)
{
int status; int status;
status = pthread_mutex_lock(&stage.mutex); status = pthread_mutex_lock(&stage.mutex);
if (status != 0) return status; if (status != 0)
return status;
/* /*
* If there's data in the pipe stage, wait for it * If there's data in the pipe stage, wait for it
@@ -90,18 +93,22 @@ int pipe_send(stage_t &stage, long data) {
* caller or the previous stage, modify the data * caller or the previous stage, modify the data
* and pass it along to the next (or final) stage. * and pass it along to the next (or final) stage.
*/ */
void *pipe_stage(void *arg) { void*
stage_t &stage = *(stage_t *)arg; pipe_stage(void* arg)
stage_t &nextStage = *stage.next; {
stage_t& stage = *(stage_t*) arg;
stage_t& nextStage = *stage.next;
int status; int status;
status = pthread_mutex_lock(&stage.mutex); status = pthread_mutex_lock(&stage.mutex);
if (status != 0) err_abort(status, "Lock pipe stage"); if (status != 0)
err_abort(status, "Lock pipe stage");
while (1) { while (1) {
while (!stage.isDataAvail) { while (!stage.isDataAvail) {
status = pthread_cond_wait(&stage.dataIsAvail, &stage.mutex); status = pthread_cond_wait(&stage.dataIsAvail, &stage.mutex);
if (status != 0) err_abort(status, "Wait for previous stage"); if (status != 0)
err_abort(status, "Wait for previous stage");
} }
pipe_send(nextStage, stage.data + 1); pipe_send(nextStage, stage.data + 1);
@@ -109,7 +116,8 @@ void *pipe_stage(void *arg) {
stage.isDataAvail = false; stage.isDataAvail = false;
status = pthread_cond_signal(&stage.threadIsIdle); status = pthread_cond_signal(&stage.threadIsIdle);
if (status != 0) err_abort(status, "Wake next stage"); if (status != 0)
err_abort(status, "Wake next stage");
} }
/* /*
@@ -126,20 +134,26 @@ void *pipe_stage(void *arg) {
* data is initialized and the threads created. They'll * data is initialized and the threads created. They'll
* wait for data. * wait for data.
*/ */
int pipe_create(pipe_t &pipe, size_t nStages) { int
pipe_create(pipe_t& pipe, size_t nStages)
{
int status = pthread_mutex_init(&pipe.mutex, NULL); int status = pthread_mutex_init(&pipe.mutex, NULL);
if (status != 0) err_abort(status, "Init pipe mutex"); if (status != 0)
err_abort(status, "Init pipe mutex");
pipe.stageList.resize(nStages); pipe.stageList.resize(nStages);
pipe.nActive = 0; pipe.nActive = 0;
for (auto &iStage : pipe.stageList) { for (auto& iStage : pipe.stageList) {
status = pthread_mutex_init(&iStage.mutex, NULL); status = pthread_mutex_init(&iStage.mutex, NULL);
if (status != 0) err_abort(status, "Init stage mutex"); if (status != 0)
err_abort(status, "Init stage mutex");
status = pthread_cond_init(&iStage.dataIsAvail, NULL); status = pthread_cond_init(&iStage.dataIsAvail, NULL);
if (status != 0) err_abort(status, "Init dataIsAvail condition"); if (status != 0)
err_abort(status, "Init dataIsAvail condition");
status = pthread_cond_init(&iStage.threadIsIdle, NULL); status = pthread_cond_init(&iStage.threadIsIdle, NULL);
if (status != 0) err_abort(status, "Init threadIsIdle condition"); if (status != 0)
err_abort(status, "Init threadIsIdle condition");
iStage.isDataAvail = false; iStage.isDataAvail = false;
} }
@@ -161,8 +175,9 @@ int pipe_create(pipe_t &pipe, size_t nStages) {
auto iit = it++; auto iit = it++;
iit->next = &(*it); iit->next = &(*it);
status = pthread_create(&iit->thread, NULL, pipe_stage, (void *)&*iit); status = pthread_create(&iit->thread, NULL, pipe_stage, (void*) &*iit);
if (status != 0) err_abort(status, "Create pipe stage"); if (status != 0)
err_abort(status, "Create pipe stage");
} }
return 0; return 0;
} }
@@ -171,11 +186,14 @@ int pipe_create(pipe_t &pipe, size_t nStages) {
* Collect the result of the pipeline. Wait for a * Collect the result of the pipeline. Wait for a
* result if the pipeline hasn't produced one. * result if the pipeline hasn't produced one.
*/ */
int pipe_result(pipe_t &pipe) { int
pipe_result(pipe_t& pipe)
{
int status; int status;
status = pthread_mutex_lock(&pipe.mutex); status = pthread_mutex_lock(&pipe.mutex);
if (status != 0) err_abort(status, "Lock pipe mutex"); if (status != 0)
err_abort(status, "Lock pipe mutex");
bool isEmpty = false; bool isEmpty = false;
if (pipe.nActive <= 0) if (pipe.nActive <= 0)
@@ -184,17 +202,19 @@ int pipe_result(pipe_t &pipe) {
pipe.nActive--; pipe.nActive--;
status = pthread_mutex_unlock(&pipe.mutex); status = pthread_mutex_unlock(&pipe.mutex);
if (status != 0) err_abort(status, "Unlock pipe mutex"); if (status != 0)
err_abort(status, "Unlock pipe mutex");
if (isEmpty) { if (isEmpty) {
printf("Pipe is empty\n"); printf("Pipe is empty\n");
return 0; return 0;
} }
auto &tail = pipe.stageList.back(); auto& tail = pipe.stageList.back();
status = pthread_mutex_lock(&tail.mutex); status = pthread_mutex_lock(&tail.mutex);
if (status != 0) err_abort(status, "Lock pipe tail mutex"); if (status != 0)
err_abort(status, "Lock pipe tail mutex");
while (!tail.isDataAvail) { while (!tail.isDataAvail) {
pthread_cond_wait(&tail.dataIsAvail, &tail.mutex); pthread_cond_wait(&tail.dataIsAvail, &tail.mutex);
@@ -204,10 +224,12 @@ int pipe_result(pipe_t &pipe) {
tail.isDataAvail = false; tail.isDataAvail = false;
status = pthread_cond_signal(&tail.threadIsIdle); status = pthread_cond_signal(&tail.threadIsIdle);
if (status != 0) err_abort(status, "Signal pipe tail threadIsIdle"); if (status != 0)
err_abort(status, "Signal pipe tail threadIsIdle");
status = pthread_mutex_unlock(&tail.mutex); status = pthread_mutex_unlock(&tail.mutex);
if (status != 0) err_abort(status, "Unlock pipe tail mutex"); if (status != 0)
err_abort(status, "Unlock pipe tail mutex");
printf("Result is %ld\n", result); printf("Result is %ld\n", result);
@@ -222,9 +244,12 @@ int pipe_result(pipe_t &pipe) {
* (note that the pipe will stall when each stage fills, * (note that the pipe will stall when each stage fills,
* until the result is collected). * until the result is collected).
*/ */
void pipe_start(pipe_t &pipe, long value) { void
pipe_start(pipe_t& pipe, long value)
{
int status = pthread_mutex_lock(&pipe.mutex); int status = pthread_mutex_lock(&pipe.mutex);
if (status != 0) err_abort(status, "Lock pipe mutex"); if (status != 0)
err_abort(status, "Lock pipe mutex");
if (pipe.nActive > pipe.stageList.size() - 1) { if (pipe.nActive > pipe.stageList.size() - 1) {
status = pthread_mutex_unlock(&pipe.mutex); status = pthread_mutex_unlock(&pipe.mutex);
@@ -235,7 +260,8 @@ void pipe_start(pipe_t &pipe, long value) {
pipe.nActive++; pipe.nActive++;
status = pthread_mutex_unlock(&pipe.mutex); status = pthread_mutex_unlock(&pipe.mutex);
if (status != 0) err_abort(status, "Unlock pipe mutex"); if (status != 0)
err_abort(status, "Unlock pipe mutex");
pipe_send(pipe.stageList.front(), value); pipe_send(pipe.stageList.front(), value);
} }
@@ -243,7 +269,9 @@ void pipe_start(pipe_t &pipe, long value) {
/* /*
* The main program to "drive" the pipeline... * The main program to "drive" the pipeline...
*/ */
int main(int argc, char *argv[]) { int
main(int argc, char* argv[])
{
pipe_t my_pipe; pipe_t my_pipe;
pipe_create(my_pipe, 2); pipe_create(my_pipe, 2);
@@ -252,12 +280,15 @@ int main(int argc, char *argv[]) {
char line[128]; char line[128];
while (1) { while (1) {
printf("Data> "); printf("Data> ");
if (fgets(line, sizeof(line), stdin) == NULL) exit(0); if (fgets(line, sizeof(line), stdin) == NULL)
exit(0);
printf(line); printf(line);
if (strlen(line) <= 1) continue; if (strlen(line) <= 1)
continue;
if (strlen(line) <= 2 && line[0] == '=') { if (strlen(line) <= 2 && line[0] == '=') {
pipe_result(my_pipe); pipe_result(my_pipe);
} else { }
else {
long value; long value;
if (sscanf(line, "%ld", &value) < 1) if (sscanf(line, "%ld", &value) < 1)
fprintf(stderr, "Enter an integer value\n"); fprintf(stderr, "Enter an integer value\n");

View File

@@ -7,8 +7,8 @@
* to allow interleaved thread execution, since threads are not * to allow interleaved thread execution, since threads are not
* timesliced. * timesliced.
*/ */
#include <pthread.h>
#include <math.h> #include <math.h>
#include <pthread.h>
#include "errors.h" #include "errors.h"
#define CLIENT_THREADS 4 /* Number of clients */ #define CLIENT_THREADS 4 /* Number of clients */
@@ -21,7 +21,7 @@
* Internal to server "package" -- one for each request. * Internal to server "package" -- one for each request.
*/ */
typedef struct request_tag { typedef struct request_tag {
struct request_tag *next; /* Link to next */ struct request_tag* next; /* Link to next */
int operation; /* Function code */ int operation; /* Function code */
int synchronous; /* Non-zero if synchronous */ int synchronous; /* Non-zero if synchronous */
int done_flag; /* Predicate for wait */ int done_flag; /* Predicate for wait */
@@ -34,16 +34,15 @@ typedef struct request_tag {
* Static context for the server * Static context for the server
*/ */
typedef struct tty_server_tag { typedef struct tty_server_tag {
request_t *first; request_t* first;
request_t *last; request_t* last;
int running; int running;
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t request; pthread_cond_t request;
} tty_server_t; } tty_server_t;
tty_server_t tty_server = { tty_server_t tty_server = {
NULL, NULL, 0, NULL, NULL, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
/* /*
* Main program data * Main program data
@@ -62,34 +61,34 @@ pthread_cond_t clients_done = PTHREAD_COND_INITIALIZER;
* responsible for freeing the request. If the request was not * responsible for freeing the request. If the request was not
* synchronous, the server will free the request on completion. * synchronous, the server will free the request on completion.
*/ */
void *tty_server_routine (void *arg) void*
tty_server_routine(void* arg)
{ {
static pthread_mutex_t prompt_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t prompt_mutex = PTHREAD_MUTEX_INITIALIZER;
request_t *request; request_t* request;
int operation, len; int operation, len;
int status; int status;
while (1) { while (1) {
status = pthread_mutex_lock (&tty_server.mutex); status = pthread_mutex_lock(&tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock server mutex"); err_abort(status, "Lock server mutex");
/* /*
* Wait for data * Wait for data
*/ */
while (tty_server.first == NULL) { while (tty_server.first == NULL) {
status = pthread_cond_wait ( status = pthread_cond_wait(&tty_server.request, &tty_server.mutex);
&tty_server.request, &tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait for request"); err_abort(status, "Wait for request");
} }
request = tty_server.first; request = tty_server.first;
tty_server.first = request->next; tty_server.first = request->next;
if (tty_server.first == NULL) if (tty_server.first == NULL)
tty_server.last = NULL; tty_server.last = NULL;
status = pthread_mutex_unlock (&tty_server.mutex); status = pthread_mutex_unlock(&tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock server mutex"); err_abort(status, "Unlock server mutex");
/* /*
* Process the data * Process the data
@@ -99,9 +98,9 @@ void *tty_server_routine (void *arg)
case REQ_QUIT: case REQ_QUIT:
break; break;
case REQ_READ: case REQ_READ:
if (strlen (request->prompt) > 0) if (strlen(request->prompt) > 0)
printf (request->prompt); printf(request->prompt);
if (fgets (request->text, 128, stdin) == NULL) if (fgets(request->text, 128, stdin) == NULL)
request->text[0] = '\0'; request->text[0] = '\0';
/* /*
* Because fgets returns the newline, and we don't want it, * Because fgets returns the newline, and we don't want it,
@@ -109,29 +108,30 @@ void *tty_server_routine (void *arg)
* input) if found. It should be the last character, if it is * input) if found. It should be the last character, if it is
* there. * there.
*/ */
len = strlen (request->text); len = strlen(request->text);
if (len > 0 && request->text[len-1] == '\n') if (len > 0 && request->text[len - 1] == '\n')
request->text[len-1] = '\0'; request->text[len - 1] = '\0';
break; break;
case REQ_WRITE: case REQ_WRITE:
puts (request->text); puts(request->text);
break; break;
default: default:
break; break;
} }
if (request->synchronous) { if (request->synchronous) {
status = pthread_mutex_lock (&tty_server.mutex); status = pthread_mutex_lock(&tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock server mutex"); err_abort(status, "Lock server mutex");
request->done_flag = 1; request->done_flag = 1;
status = pthread_cond_signal (&request->done); status = pthread_cond_signal(&request->done);
if (status != 0) if (status != 0)
err_abort (status, "Signal server condition"); err_abort(status, "Signal server condition");
status = pthread_mutex_unlock (&tty_server.mutex); status = pthread_mutex_unlock(&tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock server mutex"); err_abort(status, "Unlock server mutex");
} else }
free (request); else
free(request);
if (operation == REQ_QUIT) if (operation == REQ_QUIT)
break; break;
} }
@@ -141,34 +141,30 @@ void *tty_server_routine (void *arg)
/* /*
* Request an operation * Request an operation
*/ */
void tty_server_request ( void
int operation, tty_server_request(int operation, int sync, const char* prompt, char* string)
int sync,
const char *prompt,
char *string)
{ {
request_t *request; request_t* request;
int status; int status;
status = pthread_mutex_lock (&tty_server.mutex); status = pthread_mutex_lock(&tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock server mutex"); err_abort(status, "Lock server mutex");
if (!tty_server.running) { if (!tty_server.running) {
pthread_t thread; pthread_t thread;
pthread_attr_t detached_attr; pthread_attr_t detached_attr;
status = pthread_attr_init (&detached_attr); status = pthread_attr_init(&detached_attr);
if (status != 0) if (status != 0)
err_abort (status, "Init attributes object"); err_abort(status, "Init attributes object");
status = pthread_attr_setdetachstate ( status =
&detached_attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&detached_attr, PTHREAD_CREATE_DETACHED);
if (status != 0) if (status != 0)
err_abort (status, "Set detach state"); err_abort(status, "Set detach state");
tty_server.running = 1; tty_server.running = 1;
status = pthread_create (&thread, &detached_attr, status = pthread_create(&thread, &detached_attr, tty_server_routine, NULL);
tty_server_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create server"); err_abort(status, "Create server");
/* /*
* Ignore an error in destroying the attributes object. * Ignore an error in destroying the attributes object.
@@ -176,30 +172,30 @@ void tty_server_request (
* do about it, and it's not worth aborting the program * do about it, and it's not worth aborting the program
* over it. * over it.
*/ */
pthread_attr_destroy (&detached_attr); pthread_attr_destroy(&detached_attr);
} }
/* /*
* Create and initialize a request structure. * Create and initialize a request structure.
*/ */
request = (request_t*)malloc (sizeof (request_t)); request = (request_t*) malloc(sizeof(request_t));
if (request == NULL) if (request == NULL)
errno_abort ("Allocate request"); errno_abort("Allocate request");
request->next = NULL; request->next = NULL;
request->operation = operation; request->operation = operation;
request->synchronous = sync; request->synchronous = sync;
if (sync) { if (sync) {
request->done_flag = 0; request->done_flag = 0;
status = pthread_cond_init (&request->done, NULL); status = pthread_cond_init(&request->done, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init request condition"); err_abort(status, "Init request condition");
} }
if (prompt != NULL) if (prompt != NULL)
strncpy (request->prompt, prompt, 32); strncpy(request->prompt, prompt, 32);
else else
request->prompt[0] = '\0'; request->prompt[0] = '\0';
if (operation == REQ_WRITE && string != NULL) if (operation == REQ_WRITE && string != NULL)
strncpy (request->text, string, 128); strncpy(request->text, string, 128);
else else
request->text[0] = '\0'; request->text[0] = '\0';
@@ -210,7 +206,8 @@ void tty_server_request (
if (tty_server.first == NULL) { if (tty_server.first == NULL) {
tty_server.first = request; tty_server.first = request;
tty_server.last = request; tty_server.last = request;
} else { }
else {
(tty_server.last)->next = request; (tty_server.last)->next = request;
tty_server.last = request; tty_server.last = request;
} }
@@ -218,74 +215,74 @@ void tty_server_request (
/* /*
* Tell the server that a request is available. * Tell the server that a request is available.
*/ */
status = pthread_cond_signal (&tty_server.request); status = pthread_cond_signal(&tty_server.request);
if (status != 0) if (status != 0)
err_abort (status, "Wake server"); err_abort(status, "Wake server");
/* /*
* If the request was "synchronous", then wait for a reply. * If the request was "synchronous", then wait for a reply.
*/ */
if (sync) { if (sync) {
while (!request->done_flag) { while (!request->done_flag) {
status = pthread_cond_wait ( status = pthread_cond_wait(&request->done, &tty_server.mutex);
&request->done, &tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait for sync request"); err_abort(status, "Wait for sync request");
} }
if (operation == REQ_READ) { if (operation == REQ_READ) {
if (strlen (request->text) > 0) if (strlen(request->text) > 0)
strcpy (string, request->text); strcpy(string, request->text);
else else
string[0] = '\0'; string[0] = '\0';
} }
status = pthread_cond_destroy (&request->done); status = pthread_cond_destroy(&request->done);
if (status != 0) if (status != 0)
err_abort (status, "Destroy request condition"); err_abort(status, "Destroy request condition");
free (request); free(request);
} }
status = pthread_mutex_unlock (&tty_server.mutex); status = pthread_mutex_unlock(&tty_server.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
} }
/* /*
* Client routine -- multiple copies will request server. * Client routine -- multiple copies will request server.
*/ */
void *client_routine (void *arg) void*
client_routine(void* arg)
{ {
int my_number = (int)arg, loops; int my_number = (int) arg, loops;
char prompt[32]; char prompt[32];
char string[128], formatted[128]; char string[128], formatted[128];
int status; int status;
sprintf (prompt, "Client %d> ", my_number); sprintf(prompt, "Client %d> ", my_number);
while (1) { while (1) {
tty_server_request (REQ_READ, 1, prompt, string); tty_server_request(REQ_READ, 1, prompt, string);
if (strlen (string) == 0) if (strlen(string) == 0)
break; break;
for (loops = 0; loops < 4; loops++) { for (loops = 0; loops < 4; loops++) {
sprintf ( sprintf(formatted, "(%d#%d) %s", my_number, loops, string);
formatted, "(%d#%d) %s", my_number, loops, string); tty_server_request(REQ_WRITE, 0, NULL, formatted);
tty_server_request (REQ_WRITE, 0, NULL, formatted); sleep(1);
sleep (1);
} }
} }
status = pthread_mutex_lock (&client_mutex); status = pthread_mutex_lock(&client_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock client mutex"); err_abort(status, "Lock client mutex");
client_threads--; client_threads--;
if (client_threads <= 0) { if (client_threads <= 0) {
status = pthread_cond_signal (&clients_done); status = pthread_cond_signal(&clients_done);
if (status != 0) if (status != 0)
err_abort (status, "Signal clients done"); err_abort(status, "Signal clients done");
} }
status = pthread_mutex_unlock (&client_mutex); status = pthread_mutex_unlock(&client_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock client mutex"); err_abort(status, "Unlock client mutex");
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread; pthread_t thread;
int count; int count;
@@ -297,8 +294,8 @@ int main (int argc, char *argv[])
* that our threads can run concurrently, we need to * that our threads can run concurrently, we need to
* increase the concurrency level to CLIENT_THREADS. * increase the concurrency level to CLIENT_THREADS.
*/ */
DPRINTF (("Setting concurrency level to %d\n", CLIENT_THREADS)); DPRINTF(("Setting concurrency level to %d\n", CLIENT_THREADS));
thr_setconcurrency (CLIENT_THREADS); thr_setconcurrency(CLIENT_THREADS);
#endif #endif
/* /*
@@ -306,23 +303,22 @@ int main (int argc, char *argv[])
*/ */
client_threads = CLIENT_THREADS; client_threads = CLIENT_THREADS;
for (count = 0; count < client_threads; count++) { for (count = 0; count < client_threads; count++) {
status = pthread_create (&thread, NULL, status = pthread_create(&thread, NULL, client_routine, (void*) count);
client_routine, (void*)count);
if (status != 0) if (status != 0)
err_abort (status, "Create client thread"); err_abort(status, "Create client thread");
} }
status = pthread_mutex_lock (&client_mutex); status = pthread_mutex_lock(&client_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock client mutex"); err_abort(status, "Lock client mutex");
while (client_threads > 0) { while (client_threads > 0) {
status = pthread_cond_wait (&clients_done, &client_mutex); status = pthread_cond_wait(&clients_done, &client_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait for clients to finish"); err_abort(status, "Wait for clients to finish");
} }
status = pthread_mutex_unlock (&client_mutex); status = pthread_mutex_unlock(&client_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock client mutex"); err_abort(status, "Unlock client mutex");
printf ("All clients done\n"); printf("All clients done\n");
tty_server_request (REQ_QUIT, 1, NULL, NULL); tty_server_request(REQ_QUIT, 1, NULL, NULL);
return 0; return 0;
} }

View File

@@ -18,20 +18,22 @@ static int counter;
* when it calls pthread_testcancel, which it does each 1000 * when it calls pthread_testcancel, which it does each 1000
* iterations. * iterations.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
DPRINTF (("thread_routine starting\n")); DPRINTF(("thread_routine starting\n"));
for (counter = 0; ; counter++) for (counter = 0;; counter++)
if ((counter % 1000) == 0) { if ((counter % 1000) == 0) {
DPRINTF (("calling testcancel\n")); DPRINTF(("calling testcancel\n"));
pthread_testcancel (); pthread_testcancel();
} }
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
void *result; void* result;
int status; int status;
#ifdef sun #ifdef sun
@@ -40,27 +42,26 @@ int main (int argc, char *argv[])
* that our two threads can run concurrently, we need to * that our two threads can run concurrently, we need to
* increase the concurrency level to 2. * increase the concurrency level to 2.
*/ */
DPRINTF (("Setting concurrency level to 2\n")); DPRINTF(("Setting concurrency level to 2\n"));
thr_setconcurrency (2); thr_setconcurrency(2);
#endif #endif
status = pthread_create ( status = pthread_create(&thread_id, NULL, thread_routine, NULL);
&thread_id, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
sleep (2); sleep(2);
DPRINTF (("calling cancel\n")); DPRINTF(("calling cancel\n"));
status = pthread_cancel (thread_id); status = pthread_cancel(thread_id);
if (status != 0) if (status != 0)
err_abort (status, "Cancel thread"); err_abort(status, "Cancel thread");
DPRINTF (("calling join\n")); DPRINTF(("calling join\n"));
status = pthread_join (thread_id, &result); status = pthread_join(thread_id, &result);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
if (result == PTHREAD_CANCELED) if (result == PTHREAD_CANCELED)
printf ("Thread cancelled at iteration %d\n", counter); printf("Thread cancelled at iteration %d\n", counter);
else else
printf ("Thread was not cancelled\n"); printf("Thread was not cancelled\n");
return 0; return 0;
} }

View File

@@ -18,23 +18,23 @@ static int matrixb[SIZE][SIZE];
static int matrixc[SIZE][SIZE]; static int matrixc[SIZE][SIZE];
#ifdef DEBUG #ifdef DEBUG
void print_array (int matrix[SIZE][SIZE]) void
print_array(int matrix[SIZE][SIZE])
{ {
int i, j; int i, j;
int first; int first;
for (i = 0; i < SIZE; i++) { for (i = 0; i < SIZE; i++) {
printf ("["); printf("[");
first = 1; first = 1;
for (j = 0; j < SIZE; j++) { for (j = 0; j < SIZE; j++) {
if (!first) if (!first)
printf (","); printf(",");
printf ("%x", matrix[i][j]); printf("%x", matrix[i][j]);
first = 0; first = 0;
} }
printf ("]\n"); printf("]\n");
} }
} }
#endif #endif
@@ -44,7 +44,8 @@ void print_array (int matrix[SIZE][SIZE])
* is enabled. The loop multiplies the two matrices matrixa * is enabled. The loop multiplies the two matrices matrixa
* and matrixb. * and matrixb.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
int cancel_type, status; int cancel_type, status;
int i, j, k, value = 1; int i, j, k, value = 1;
@@ -62,36 +63,32 @@ void *thread_routine (void *arg)
/* /*
* Compute the matrix product of matrixa and matrixb. * Compute the matrix product of matrixa and matrixb.
*/ */
status = pthread_setcanceltype ( status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &cancel_type);
PTHREAD_CANCEL_ASYNCHRONOUS,
&cancel_type);
if (status != 0) if (status != 0)
err_abort (status, "Set cancel type"); err_abort(status, "Set cancel type");
for (i = 0; i < SIZE; i++) for (i = 0; i < SIZE; i++)
for (j = 0; j < SIZE; j++) { for (j = 0; j < SIZE; j++) {
matrixc[i][j] = 0; matrixc[i][j] = 0;
for (k = 0; k < SIZE; k++) for (k = 0; k < SIZE; k++)
matrixc[i][j] += matrixa[i][k] * matrixb[k][j]; matrixc[i][j] += matrixa[i][k] * matrixb[k][j];
} }
status = pthread_setcanceltype ( status = pthread_setcanceltype(cancel_type, &cancel_type);
cancel_type,
&cancel_type);
if (status != 0) if (status != 0)
err_abort (status, "Set cancel type"); err_abort(status, "Set cancel type");
/* /*
* Copy the result (matrixc) into matrixa to start again * Copy the result (matrixc) into matrixa to start again
*/ */
for (i = 0; i < SIZE; i++) for (i = 0; i < SIZE; i++)
for (j = 0; j < SIZE; j++) for (j = 0; j < SIZE; j++) matrixa[i][j] = matrixc[i][j];
matrixa[i][j] = matrixc[i][j];
} }
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
void *result; void* result;
int status; int status;
#ifdef sun #ifdef sun
@@ -100,31 +97,30 @@ int main (int argc, char *argv[])
* that our two threads can run concurrently, we need to * that our two threads can run concurrently, we need to
* increase the concurrency level to 2. * increase the concurrency level to 2.
*/ */
DPRINTF (("Setting concurrency level to 2\n")); DPRINTF(("Setting concurrency level to 2\n"));
thr_setconcurrency (2); thr_setconcurrency(2);
#endif #endif
status = pthread_create ( status = pthread_create(&thread_id, NULL, thread_routine, NULL);
&thread_id, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
sleep (1); sleep(1);
status = pthread_cancel (thread_id); status = pthread_cancel(thread_id);
if (status != 0) if (status != 0)
err_abort (status, "Cancel thread"); err_abort(status, "Cancel thread");
status = pthread_join (thread_id, &result); status = pthread_join(thread_id, &result);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
if (result == PTHREAD_CANCELED) if (result == PTHREAD_CANCELED)
printf ("Thread cancelled\n"); printf("Thread cancelled\n");
else else
printf ("Thread was not cancelled\n"); printf("Thread was not cancelled\n");
#ifdef DEBUG #ifdef DEBUG
printf ("Matrix a:\n"); printf("Matrix a:\n");
print_array (matrixa); print_array(matrixa);
printf ("\nMatrix b:\n"); printf("\nMatrix b:\n");
print_array (matrixb); print_array(matrixb);
printf ("\nMatrix c:\n"); printf("\nMatrix c:\n");
print_array (matrixc); print_array(matrixc);
#endif #endif
return 0; return 0;
} }

View File

@@ -19,24 +19,24 @@ typedef struct control_tag {
pthread_cond_t cv; pthread_cond_t cv;
} control_t; } control_t;
control_t control = control_t control = {0, 1, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
{0, 1, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
/* /*
* This routine is installed as the cancellation cleanup * This routine is installed as the cancellation cleanup
* handler around the cancellable condition wait. It will * handler around the cancellable condition wait. It will
* be called by the system when the thread is cancelled. * be called by the system when the thread is cancelled.
*/ */
void cleanup_handler (void *arg) void
cleanup_handler(void* arg)
{ {
control_t *st = (control_t *)arg; control_t* st = (control_t*) arg;
int status; int status;
st->counter--; st->counter--;
printf ("cleanup_handler: counter == %d\n", st->counter); printf("cleanup_handler: counter == %d\n", st->counter);
status = pthread_mutex_unlock (&st->mutex); status = pthread_mutex_unlock(&st->mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock in cleanup handler"); err_abort(status, "Unlock in cleanup handler");
} }
/* /*
@@ -46,55 +46,56 @@ void cleanup_handler (void *arg)
* nonzero value to pthread_cleanup_pop to run the same * nonzero value to pthread_cleanup_pop to run the same
* "finalization" action when cancellation does not occur. * "finalization" action when cancellation does not occur.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
int status; int status;
pthread_cleanup_push (cleanup_handler, (void*)&control); pthread_cleanup_push(cleanup_handler, (void*) &control);
status = pthread_mutex_lock (&control.mutex); status = pthread_mutex_lock(&control.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Mutex lock"); err_abort(status, "Mutex lock");
control.counter++; control.counter++;
while (control.busy) { while (control.busy) {
status = pthread_cond_wait (&control.cv, &control.mutex); status = pthread_cond_wait(&control.cv, &control.mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait on condition"); err_abort(status, "Wait on condition");
} }
pthread_cleanup_pop (1); pthread_cleanup_pop(1);
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id[THREADS]; pthread_t thread_id[THREADS];
int count; int count;
void *result; void* result;
int status; int status;
for (count = 0; count < THREADS; count++) { for (count = 0; count < THREADS; count++) {
status = pthread_create ( status = pthread_create(&thread_id[count], NULL, thread_routine, NULL);
&thread_id[count], NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
sleep (2); sleep(2);
for (count = 0; count < THREADS; count++) { for (count = 0; count < THREADS; count++) {
status = pthread_cancel (thread_id[count]); status = pthread_cancel(thread_id[count]);
if (status != 0) if (status != 0)
err_abort (status, "Cancel thread"); err_abort(status, "Cancel thread");
status = pthread_join (thread_id[count], &result); status = pthread_join(thread_id[count], &result);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
if (result == PTHREAD_CANCELED) if (result == PTHREAD_CANCELED)
printf ("thread %d cancelled\n", count); printf("thread %d cancelled\n", count);
else else
printf ("thread %d was not cancelled\n", count); printf("thread %d was not cancelled\n", count);
} }
return 0; return 0;
} }

View File

@@ -12,13 +12,13 @@ static int counter;
/* /*
* Thread start routine. * Thread start routine.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
int state; int state;
int status; int status;
for (counter = 0; ; counter++) { for (counter = 0;; counter++) {
/* /*
* Each 755 iterations, disable cancellation and sleep * Each 755 iterations, disable cancellation and sleep
* for one second. * for one second.
@@ -27,42 +27,40 @@ void *thread_routine (void *arg)
* calling pthread_testcancel(). * calling pthread_testcancel().
*/ */
if ((counter % 755) == 0) { if ((counter % 755) == 0) {
status = pthread_setcancelstate ( status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
PTHREAD_CANCEL_DISABLE, &state);
if (status != 0) if (status != 0)
err_abort (status, "Disable cancel"); err_abort(status, "Disable cancel");
sleep (1); sleep(1);
status = pthread_setcancelstate ( status = pthread_setcancelstate(state, &state);
state, &state);
if (status != 0) if (status != 0)
err_abort (status, "Restore cancel"); err_abort(status, "Restore cancel");
} else }
if ((counter % 1000) == 0) else if ((counter % 1000) == 0)
pthread_testcancel (); pthread_testcancel();
} }
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
void *result; void* result;
int status; int status;
status = pthread_create ( status = pthread_create(&thread_id, NULL, thread_routine, NULL);
&thread_id, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
sleep (2); sleep(2);
status = pthread_cancel (thread_id); status = pthread_cancel(thread_id);
if (status != 0) if (status != 0)
err_abort (status, "Cancel thread"); err_abort(status, "Cancel thread");
status = pthread_join (thread_id, &result); status = pthread_join(thread_id, &result);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
if (result == PTHREAD_CANCELED) if (result == PTHREAD_CANCELED)
printf ("Thread cancelled at iteration %d\n", counter); printf("Thread cancelled at iteration %d\n", counter);
else else
printf ("Thread was not cancelled\n"); printf("Thread was not cancelled\n");
return 0; return 0;
} }

View File

@@ -26,33 +26,35 @@ typedef struct team_tag {
* Start routine for worker threads. They loop waiting for a * Start routine for worker threads. They loop waiting for a
* cancellation request. * cancellation request.
*/ */
void *worker_routine (void *arg) void*
worker_routine(void* arg)
{ {
int counter; int counter;
for (counter = 0; ; counter++) for (counter = 0;; counter++)
if ((counter % 1000) == 0) if ((counter % 1000) == 0)
pthread_testcancel (); pthread_testcancel();
} }
/* /*
* Cancellation cleanup handler for the contractor thread. It * Cancellation cleanup handler for the contractor thread. It
* will cancel and detach each worker in the team. * will cancel and detach each worker in the team.
*/ */
void cleanup (void *arg) void
cleanup(void* arg)
{ {
team_t *team = (team_t *)arg; team_t* team = (team_t*) arg;
int count, status; int count, status;
for (count = team->join_i; count < THREADS; count++) { for (count = team->join_i; count < THREADS; count++) {
status = pthread_cancel (team->workers[count]); status = pthread_cancel(team->workers[count]);
if (status != 0) if (status != 0)
err_abort (status, "Cancel worker"); err_abort(status, "Cancel worker");
status = pthread_detach (team->workers[count]); status = pthread_detach(team->workers[count]);
if (status != 0) if (status != 0)
err_abort (status, "Detach worker"); err_abort(status, "Detach worker");
printf ("Cleanup: cancelled %d\n", count); printf("Cleanup: cancelled %d\n", count);
} }
} }
@@ -61,32 +63,33 @@ void cleanup (void *arg)
* worker threads, and then joins with them. When cancelled, the * worker threads, and then joins with them. When cancelled, the
* cleanup handler will cancel and detach the remaining threads. * cleanup handler will cancel and detach the remaining threads.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
team_t team; /* team info */ team_t team; /* team info */
int count; int count;
void *result; /* Return status */ void* result; /* Return status */
int status; int status;
for (count = 0; count < THREADS; count++) { for (count = 0; count < THREADS; count++) {
status = pthread_create ( status = pthread_create(&team.workers[count], NULL, worker_routine, NULL);
&team.workers[count], NULL, worker_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create worker"); err_abort(status, "Create worker");
} }
pthread_cleanup_push (cleanup, (void*)&team); pthread_cleanup_push(cleanup, (void*) &team);
for (team.join_i = 0; team.join_i < THREADS; team.join_i++) { for (team.join_i = 0; team.join_i < THREADS; team.join_i++) {
status = pthread_join (team.workers[team.join_i], &result); status = pthread_join(team.workers[team.join_i], &result);
if (status != 0) if (status != 0)
err_abort (status, "Join worker"); err_abort(status, "Join worker");
} }
pthread_cleanup_pop (0); pthread_cleanup_pop(0);
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
int status; int status;
@@ -98,18 +101,18 @@ int main (int argc, char *argv[])
* increase the concurrency level to at least 2 plus THREADS * increase the concurrency level to at least 2 plus THREADS
* (the number of workers). * (the number of workers).
*/ */
DPRINTF (("Setting concurrency level to %d\n", THREADS+2)); DPRINTF(("Setting concurrency level to %d\n", THREADS + 2));
thr_setconcurrency (THREADS+2); thr_setconcurrency(THREADS + 2);
#endif #endif
status = pthread_create (&thread_id, NULL, thread_routine, NULL); status = pthread_create(&thread_id, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create team"); err_abort(status, "Create team");
sleep (5); sleep(5);
printf ("Cancelling...\n"); printf("Cancelling...\n");
status = pthread_cancel (thread_id); status = pthread_cancel(thread_id);
if (status != 0) if (status != 0)
err_abort (status, "Cancel team"); err_abort(status, "Cancel team");
status = pthread_join (thread_id, NULL); status = pthread_join(thread_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join team"); err_abort(status, "Join team");
} }

View File

@@ -13,22 +13,22 @@
pthread_cond_t cond; pthread_cond_t cond;
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_condattr_t cond_attr; pthread_condattr_t cond_attr;
int status; int status;
status = pthread_condattr_init (&cond_attr); status = pthread_condattr_init(&cond_attr);
if (status != 0) if (status != 0)
err_abort (status, "Create attr"); err_abort(status, "Create attr");
#ifdef _POSIX_THREAD_PROCESS_SHARED #ifdef _POSIX_THREAD_PROCESS_SHARED
status = pthread_condattr_setpshared ( status = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_PRIVATE);
&cond_attr, PTHREAD_PROCESS_PRIVATE);
if (status != 0) if (status != 0)
err_abort (status, "Set pshared"); err_abort(status, "Set pshared");
#endif #endif
status = pthread_cond_init (&cond, &cond_attr); status = pthread_cond_init(&cond, &cond_attr);
if (status != 0) if (status != 0)
err_abort (status, "Init cond"); err_abort(status, "Init cond");
return 0; return 0;
} }

View File

@@ -14,22 +14,22 @@
pthread_mutex_t mutex; pthread_mutex_t mutex;
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_mutexattr_t mutex_attr; pthread_mutexattr_t mutex_attr;
int status; int status;
status = pthread_mutexattr_init (&mutex_attr); status = pthread_mutexattr_init(&mutex_attr);
if (status != 0) if (status != 0)
err_abort (status, "Create attr"); err_abort(status, "Create attr");
#ifdef _POSIX_THREAD_PROCESS_SHARED #ifdef _POSIX_THREAD_PROCESS_SHARED
status = pthread_mutexattr_setpshared ( status = pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_PRIVATE);
&mutex_attr, PTHREAD_PROCESS_PRIVATE);
if (status != 0) if (status != 0)
err_abort (status, "Set pshared"); err_abort(status, "Set pshared");
#endif #endif
status = pthread_mutex_init (&mutex, &mutex_attr); status = pthread_mutex_init(&mutex, &mutex_attr);
if (status != 0) if (status != 0)
err_abort (status, "Init mutex"); err_abort(status, "Init mutex");
return 0; return 0;
} }

View File

@@ -16,56 +16,59 @@ pthread_mutex_t mutex;
* with the same control structure are made during the course of * with the same control structure are made during the course of
* the program. * the program.
*/ */
void once_init_routine (void) void
once_init_routine(void)
{ {
int status; int status;
status = pthread_mutex_init (&mutex, NULL); status = pthread_mutex_init(&mutex, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Init Mutex"); err_abort(status, "Init Mutex");
} }
/* /*
* Thread start routine that calls pthread_once. * Thread start routine that calls pthread_once.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
int status; int status;
status = pthread_once (&once_block, once_init_routine); status = pthread_once(&once_block, once_init_routine);
if (status != 0) if (status != 0)
err_abort (status, "Once init"); err_abort(status, "Once init");
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
printf ("thread_routine has locked the mutex.\n"); printf("thread_routine has locked the mutex.\n");
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
char *input, buffer[64]; char *input, buffer[64];
int status; int status;
status = pthread_create (&thread_id, NULL, thread_routine, NULL); status = pthread_create(&thread_id, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_once (&once_block, once_init_routine); status = pthread_once(&once_block, once_init_routine);
if (status != 0) if (status != 0)
err_abort (status, "Once init"); err_abort(status, "Once init");
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
printf ("Main has locked the mutex.\n"); printf("Main has locked the mutex.\n");
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
status = pthread_join (thread_id, NULL); status = pthread_join(thread_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
return 0; return 0;
} }

View File

@@ -9,16 +9,17 @@
* _POSIX_THREAD_PRIORITY_SCHEDULING, it does not support the * _POSIX_THREAD_PRIORITY_SCHEDULING, it does not support the
* SCHED_RR policy for threads. * SCHED_RR policy for threads.
*/ */
#include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
#include <unistd.h>
#include "errors.h" #include "errors.h"
/* /*
* Thread start routine. If priority scheduling is supported, * Thread start routine. If priority scheduling is supported,
* report the thread's scheduling attributes. * report the thread's scheduling attributes.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
int my_policy; int my_policy;
struct sched_param my_param; struct sched_param my_param;
@@ -29,24 +30,25 @@ void *thread_routine (void *arg)
* can do nothing with the output of pthread_getschedparam, * can do nothing with the output of pthread_getschedparam,
* so just report that the thread ran, and exit. * so just report that the thread ran, and exit.
*/ */
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined (sun) #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined(sun)
status = pthread_getschedparam ( status = pthread_getschedparam(pthread_self(), &my_policy, &my_param);
pthread_self (), &my_policy, &my_param);
if (status != 0) if (status != 0)
err_abort (status, "Get sched"); err_abort(status, "Get sched");
printf ("thread_routine running at %s/%d\n", printf("thread_routine running at %s/%d\n",
(my_policy == SCHED_FIFO ? "FIFO" (my_policy == SCHED_FIFO
: (my_policy == SCHED_RR ? "RR" ? "FIFO"
: (my_policy == SCHED_OTHER ? "OTHER" : (my_policy == SCHED_RR
: "unknown"))), ? "RR"
: (my_policy == SCHED_OTHER ? "OTHER" : "unknown"))),
my_param.sched_priority); my_param.sched_priority);
#else #else
printf ("thread_routine running\n"); printf("thread_routine running\n");
#endif #endif
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
@@ -54,9 +56,9 @@ int main (int argc, char *argv[])
struct sched_param thread_param; struct sched_param thread_param;
int status, rr_min_priority, rr_max_priority; int status, rr_min_priority, rr_max_priority;
status = pthread_attr_init (&thread_attr); status = pthread_attr_init(&thread_attr);
if (status != 0) if (status != 0)
err_abort (status, "Init attr"); err_abort(status, "Init attr");
/* /*
* If the priority scheduling option is defined, set various scheduling * If the priority scheduling option is defined, set various scheduling
@@ -66,27 +68,24 @@ int main (int argc, char *argv[])
* behavior is to inherit scheduling information from the creating * behavior is to inherit scheduling information from the creating
* thread. * thread.
*/ */
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined (sun) #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined(sun)
status = pthread_attr_getschedpolicy ( status = pthread_attr_getschedpolicy(&thread_attr, &thread_policy);
&thread_attr, &thread_policy);
if (status != 0) if (status != 0)
err_abort (status, "Get policy"); err_abort(status, "Get policy");
status = pthread_attr_getschedparam ( status = pthread_attr_getschedparam(&thread_attr, &thread_param);
&thread_attr, &thread_param);
if (status != 0) if (status != 0)
err_abort (status, "Get sched param"); err_abort(status, "Get sched param");
printf ( printf("Default policy is %s, priority is %d\n",
"Default policy is %s, priority is %d\n", (thread_policy == SCHED_FIFO
(thread_policy == SCHED_FIFO ? "FIFO" ? "FIFO"
: (thread_policy == SCHED_RR ? "RR" : (thread_policy == SCHED_RR
: (thread_policy == SCHED_OTHER ? "OTHER" ? "RR"
: "unknown"))), : (thread_policy == SCHED_OTHER ? "OTHER" : "unknown"))),
thread_param.sched_priority); thread_param.sched_priority);
status = pthread_attr_setschedpolicy ( status = pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
&thread_attr, SCHED_RR);
if (status != 0) if (status != 0)
printf ("Unable to set SCHED_RR policy.\n"); printf("Unable to set SCHED_RR policy.\n");
else { else {
/* /*
* Just for the sake of the exercise, we'll use the * Just for the sake of the exercise, we'll use the
@@ -99,41 +98,34 @@ int main (int argc, char *argv[])
* defaults to System contention scope, you may have to * defaults to System contention scope, you may have to
* adjust this code before it will work on some systems. * adjust this code before it will work on some systems.
*/ */
rr_min_priority = sched_get_priority_min (SCHED_RR); rr_min_priority = sched_get_priority_min(SCHED_RR);
if (rr_min_priority == -1) if (rr_min_priority == -1)
errno_abort ("Get SCHED_RR min priority"); errno_abort("Get SCHED_RR min priority");
rr_max_priority = sched_get_priority_max (SCHED_RR); rr_max_priority = sched_get_priority_max(SCHED_RR);
if (rr_max_priority == -1) if (rr_max_priority == -1)
errno_abort ("Get SCHED_RR max priority"); errno_abort("Get SCHED_RR max priority");
thread_param.sched_priority = thread_param.sched_priority = (rr_min_priority + rr_max_priority) / 2;
(rr_min_priority + rr_max_priority)/2; printf("SCHED_RR priority range is %d to %d: using %d\n",
printf (
"SCHED_RR priority range is %d to %d: using %d\n",
rr_min_priority, rr_min_priority,
rr_max_priority, rr_max_priority,
thread_param.sched_priority); thread_param.sched_priority);
status = pthread_attr_setschedparam ( status = pthread_attr_setschedparam(&thread_attr, &thread_param);
&thread_attr, &thread_param);
if (status != 0) if (status != 0)
err_abort (status, "Set params"); err_abort(status, "Set params");
printf ( printf("Creating thread at RR/%d\n", thread_param.sched_priority);
"Creating thread at RR/%d\n", status = pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
thread_param.sched_priority);
status = pthread_attr_setinheritsched (
&thread_attr, PTHREAD_EXPLICIT_SCHED);
if (status != 0) if (status != 0)
err_abort (status, "Set inherit"); err_abort(status, "Set inherit");
} }
#else #else
printf ("Priority scheduling not supported\n"); printf("Priority scheduling not supported\n");
#endif #endif
status = pthread_create ( status = pthread_create(&thread_id, &thread_attr, thread_routine, NULL);
&thread_id, &thread_attr, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_join (thread_id, NULL); status = pthread_join(thread_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
printf ("Main exiting\n"); printf("Main exiting\n");
return 0; return 0;
} }

View File

@@ -6,9 +6,9 @@
* Special note: This demonstration will fail on Solaris 2.5 * Special note: This demonstration will fail on Solaris 2.5
* because it does not implement SCHED_RR. * because it does not implement SCHED_RR.
*/ */
#include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
#include <unistd.h>
#include "errors.h" #include "errors.h"
#define THREADS 5 #define THREADS 5
@@ -27,62 +27,62 @@ int rr_min_priority;
/* /*
* Thread start routine that will set its own priority * Thread start routine that will set its own priority
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
thread_t *self = (thread_t*)arg; thread_t* self = (thread_t*) arg;
int my_policy; int my_policy;
struct sched_param my_param; struct sched_param my_param;
int status; int status;
my_param.sched_priority = rr_min_priority + self->index; my_param.sched_priority = rr_min_priority + self->index;
DPRINTF (( DPRINTF(("Thread %d will set SCHED_FIFO, priority %d\n",
"Thread %d will set SCHED_FIFO, priority %d\n",
self->index, my_param.sched_priority));
status = pthread_setschedparam (
self->id, SCHED_RR, &my_param);
if (status != 0)
err_abort (status, "Set sched");
status = pthread_getschedparam (
self->id, &my_policy, &my_param);
if (status != 0)
err_abort (status, "Get sched");
printf ("thread_routine %d running at %s/%d\n",
self->index, self->index,
(my_policy == SCHED_FIFO ? "FIFO" my_param.sched_priority));
: (my_policy == SCHED_RR ? "RR" status = pthread_setschedparam(self->id, SCHED_RR, &my_param);
: (my_policy == SCHED_OTHER ? "OTHER" if (status != 0)
: "unknown"))), err_abort(status, "Set sched");
status = pthread_getschedparam(self->id, &my_policy, &my_param);
if (status != 0)
err_abort(status, "Get sched");
printf("thread_routine %d running at %s/%d\n",
self->index,
(my_policy == SCHED_FIFO
? "FIFO"
: (my_policy == SCHED_RR
? "RR"
: (my_policy == SCHED_OTHER ? "OTHER" : "unknown"))),
my_param.sched_priority); my_param.sched_priority);
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int count, status; int count, status;
rr_min_priority = sched_get_priority_min (SCHED_RR); rr_min_priority = sched_get_priority_min(SCHED_RR);
if (rr_min_priority == -1) { if (rr_min_priority == -1) {
#ifdef sun #ifdef sun
if (errno == ENOSYS) { if (errno == ENOSYS) {
fprintf (stderr, "SCHED_RR is not supported.\n"); fprintf(stderr, "SCHED_RR is not supported.\n");
exit (0); exit(0);
} }
#endif #endif
errno_abort ("Get SCHED_RR min priority"); errno_abort("Get SCHED_RR min priority");
} }
for (count = 0; count < THREADS; count++) { for (count = 0; count < THREADS; count++) {
threads[count].index = count; threads[count].index = count;
status = pthread_create ( status = pthread_create(
&threads[count].id, NULL, &threads[count].id, NULL, thread_routine, (void*) &threads[count]);
thread_routine, (void*)&threads[count]);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
for (count = 0; count < THREADS; count++) { for (count = 0; count < THREADS; count++) {
status = pthread_join (threads[count].id, NULL); status = pthread_join(threads[count].id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
} }
printf ("Main exiting\n"); printf("Main exiting\n");
return 0; return 0;
} }

View File

@@ -14,13 +14,15 @@
/* /*
* Thread start routine that reports it ran, and then exits. * Thread start routine that reports it ran, and then exits.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
printf ("The thread is here\n"); printf("The thread is here\n");
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
@@ -28,17 +30,16 @@ int main (int argc, char *argv[])
size_t stack_size; size_t stack_size;
int status; int status;
status = pthread_attr_init (&thread_attr); status = pthread_attr_init(&thread_attr);
if (status != 0) if (status != 0)
err_abort (status, "Create attr"); err_abort(status, "Create attr");
/* /*
* Create a detached thread. * Create a detached thread.
*/ */
status = pthread_attr_setdetachstate ( status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
&thread_attr, PTHREAD_CREATE_DETACHED);
if (status != 0) if (status != 0)
err_abort (status, "Set detach"); err_abort(status, "Set detach");
#ifdef _POSIX_THREAD_ATTR_STACKSIZE #ifdef _POSIX_THREAD_ATTR_STACKSIZE
/* /*
* If supported, determine the default stack size and report * If supported, determine the default stack size and report
@@ -49,21 +50,20 @@ int main (int argc, char *argv[])
* not be the size that will actually be used. Solaris 2.5 * not be the size that will actually be used. Solaris 2.5
* uses a value of 0 to indicate the default. * uses a value of 0 to indicate the default.
*/ */
status = pthread_attr_getstacksize (&thread_attr, &stack_size); status = pthread_attr_getstacksize(&thread_attr, &stack_size);
if (status != 0) if (status != 0)
err_abort (status, "Get stack size"); err_abort(status, "Get stack size");
printf ("Default stack size is %u; minimum is %u\n", printf("Default stack size is %u; minimum is %u\n",
stack_size, PTHREAD_STACK_MIN); stack_size,
status = pthread_attr_setstacksize ( PTHREAD_STACK_MIN);
&thread_attr, PTHREAD_STACK_MIN*2); status = pthread_attr_setstacksize(&thread_attr, PTHREAD_STACK_MIN * 2);
if (status != 0) if (status != 0)
err_abort (status, "Set stack size"); err_abort(status, "Set stack size");
#endif #endif
status = pthread_create ( status = pthread_create(&thread_id, &thread_attr, thread_routine, NULL);
&thread_id, &thread_attr, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
printf ("Main exiting\n"); printf("Main exiting\n");
pthread_exit (NULL); pthread_exit(NULL);
return 0; return 0;
} }

View File

@@ -11,7 +11,7 @@
*/ */
typedef struct private_tag { typedef struct private_tag {
pthread_t thread_id; pthread_t thread_id;
char *string; char* string;
} private_t; } private_t;
pthread_key_t identity_key; /* Thread-specific data key */ pthread_key_t identity_key; /* Thread-specific data key */
@@ -24,45 +24,47 @@ long identity_key_counter = 0;
* threads still have values, and deletes the key when there are * threads still have values, and deletes the key when there are
* no more references. * no more references.
*/ */
void identity_key_destructor (void *value) void
identity_key_destructor(void* value)
{ {
private_t *private = (private_t*)value; private_t* private = (private_t*) value;
int status; int status;
printf ("thread \"%s\" exiting...\n", private->string); printf("thread \"%s\" exiting...\n", private->string);
free (value); free(value);
status = pthread_mutex_lock (&identity_key_mutex); status = pthread_mutex_lock(&identity_key_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock key mutex"); err_abort(status, "Lock key mutex");
identity_key_counter--; identity_key_counter--;
if (identity_key_counter <= 0) { if (identity_key_counter <= 0) {
status = pthread_key_delete (identity_key); status = pthread_key_delete(identity_key);
if (status != 0) if (status != 0)
err_abort (status, "Delete key"); err_abort(status, "Delete key");
printf ("key deleted...\n"); printf("key deleted...\n");
} }
status = pthread_mutex_unlock (&identity_key_mutex); status = pthread_mutex_unlock(&identity_key_mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock key mutex"); err_abort(status, "Unlock key mutex");
} }
/* /*
* Helper routine to allocate a new value for thread-specific * Helper routine to allocate a new value for thread-specific
* data key if the thread doesn't already have one. * data key if the thread doesn't already have one.
*/ */
void *identity_key_get (void) void*
identity_key_get(void)
{ {
void *value; void* value;
int status; int status;
value = pthread_getspecific (identity_key); value = pthread_getspecific(identity_key);
if (value == NULL) { if (value == NULL) {
value = malloc (sizeof (private_t)); value = malloc(sizeof(private_t));
if (value == NULL) if (value == NULL)
errno_abort ("Allocate key value"); errno_abort("Allocate key value");
status = pthread_setspecific (identity_key, (void*)value); status = pthread_setspecific(identity_key, (void*) value);
if (status != 0) if (status != 0)
err_abort (status, "Set TSD"); err_abort(status, "Set TSD");
} }
return value; return value;
} }
@@ -70,22 +72,24 @@ void *identity_key_get (void)
/* /*
* Thread start routine to use thread-specific data. * Thread start routine to use thread-specific data.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
private_t *value; private_t* value;
value = (private_t*)identity_key_get (); value = (private_t*) identity_key_get();
value->thread_id = pthread_self (); value->thread_id = pthread_self();
value->string = (char*)arg; value->string = (char*) arg;
printf ("thread \"%s\" starting...\n", value->string); printf("thread \"%s\" starting...\n", value->string);
sleep (2); sleep(2);
return NULL; return NULL;
} }
void main (int argc, char *argv[]) void
main(int argc, char* argv[])
{ {
pthread_t thread_1, thread_2; pthread_t thread_1, thread_2;
private_t *value; private_t* value;
int status; int status;
/* /*
@@ -99,20 +103,18 @@ void main (int argc, char *argv[])
* Note that there's rarely any good reason to delete a * Note that there's rarely any good reason to delete a
* thread-specific data key. * thread-specific data key.
*/ */
status = pthread_key_create (&identity_key, identity_key_destructor); status = pthread_key_create(&identity_key, identity_key_destructor);
if (status != 0) if (status != 0)
err_abort (status, "Create key"); err_abort(status, "Create key");
identity_key_counter = 3; identity_key_counter = 3;
value = (private_t*)identity_key_get (); value = (private_t*) identity_key_get();
value->thread_id = pthread_self (); value->thread_id = pthread_self();
value->string = "Main thread"; value->string = "Main thread";
status = pthread_create (&thread_1, NULL, status = pthread_create(&thread_1, NULL, thread_routine, "Thread 1");
thread_routine, "Thread 1");
if (status != 0) if (status != 0)
err_abort (status, "Create thread 1"); err_abort(status, "Create thread 1");
status = pthread_create (&thread_2, NULL, status = pthread_create(&thread_2, NULL, thread_routine, "Thread 2");
thread_routine, "Thread 2");
if (status != 0) if (status != 0)
err_abort (status, "Create thread 2"); err_abort(status, "Create thread 2");
pthread_exit (NULL); pthread_exit(NULL);
} }

View File

@@ -15,7 +15,7 @@
*/ */
typedef struct tsd_tag { typedef struct tsd_tag {
pthread_t thread_id; pthread_t thread_id;
char *string; char* string;
} tsd_t; } tsd_t;
pthread_key_t tsd_key; /* Thread-specific data key */ pthread_key_t tsd_key; /* Thread-specific data key */
@@ -25,57 +25,58 @@ pthread_once_t key_once = PTHREAD_ONCE_INIT;
* One-time initialization routine used with the pthread_once * One-time initialization routine used with the pthread_once
* control block. * control block.
*/ */
void once_routine (void) void
once_routine(void)
{ {
int status; int status;
printf ("initializing key\n"); printf("initializing key\n");
status = pthread_key_create (&tsd_key, NULL); status = pthread_key_create(&tsd_key, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create key"); err_abort(status, "Create key");
} }
/* /*
* Thread start routine that uses pthread_once to dynamically * Thread start routine that uses pthread_once to dynamically
* create a thread-specific data key. * create a thread-specific data key.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
tsd_t *value; tsd_t* value;
int status; int status;
status = pthread_once (&key_once, once_routine); status = pthread_once(&key_once, once_routine);
if (status != 0) if (status != 0)
err_abort (status, "Once init"); err_abort(status, "Once init");
value = (tsd_t*)malloc (sizeof (tsd_t)); value = (tsd_t*) malloc(sizeof(tsd_t));
if (value == NULL) if (value == NULL)
errno_abort ("Allocate key value"); errno_abort("Allocate key value");
status = pthread_setspecific (tsd_key, value); status = pthread_setspecific(tsd_key, value);
if (status != 0) if (status != 0)
err_abort (status, "Set tsd"); err_abort(status, "Set tsd");
printf ("%s set tsd value %p\n", arg, value); printf("%s set tsd value %p\n", arg, value);
value->thread_id = pthread_self (); value->thread_id = pthread_self();
value->string = (char*)arg; value->string = (char*) arg;
value = (tsd_t*)pthread_getspecific (tsd_key); value = (tsd_t*) pthread_getspecific(tsd_key);
printf ("%s starting...\n", value->string); printf("%s starting...\n", value->string);
sleep (2); sleep(2);
value = (tsd_t*)pthread_getspecific (tsd_key); value = (tsd_t*) pthread_getspecific(tsd_key);
printf ("%s done...\n", value->string); printf("%s done...\n", value->string);
return NULL; return NULL;
} }
void main (int argc, char *argv[]) void
main(int argc, char* argv[])
{ {
pthread_t thread1, thread2; pthread_t thread1, thread2;
int status; int status;
status = pthread_create ( status = pthread_create(&thread1, NULL, thread_routine, "thread 1");
&thread1, NULL, thread_routine, "thread 1");
if (status != 0) if (status != 0)
err_abort (status, "Create thread 1"); err_abort(status, "Create thread 1");
status = pthread_create ( status = pthread_create(&thread2, NULL, thread_routine, "thread 2");
&thread2, NULL, thread_routine, "thread 2");
if (status != 0) if (status != 0)
err_abort (status, "Create thread 2"); err_abort(status, "Create thread 2");
pthread_exit (NULL); pthread_exit(NULL);
} }

View File

@@ -4,8 +4,8 @@
* Demonstrate the use of "fork handlers" to protect data * Demonstrate the use of "fork handlers" to protect data
* invariants across a fork. * invariants across a fork.
*/ */
#include <sys/types.h>
#include <pthread.h> #include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include "errors.h" #include "errors.h"
@@ -16,7 +16,8 @@ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
* This routine will be called prior to executing the fork, * This routine will be called prior to executing the fork,
* within the parent process. * within the parent process.
*/ */
void fork_prepare (void) void
fork_prepare(void)
{ {
int status; int status;
@@ -25,32 +26,34 @@ void fork_prepare (void)
* to ensure that no other thread can lock it (or change any * to ensure that no other thread can lock it (or change any
* associated shared state) until after the fork completes. * associated shared state) until after the fork completes.
*/ */
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock in prepare handler"); err_abort(status, "Lock in prepare handler");
} }
/* /*
* This routine will be called after executing the fork, within * This routine will be called after executing the fork, within
* the parent process * the parent process
*/ */
void fork_parent (void) void
fork_parent(void)
{ {
int status; int status;
/* /*
* Unlock the mutex in the parent after the child has been created. * Unlock the mutex in the parent after the child has been created.
*/ */
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock in parent handler"); err_abort(status, "Unlock in parent handler");
} }
/* /*
* This routine will be called after executing the fork, within * This routine will be called after executing the fork, within
* the child process * the child process
*/ */
void fork_child (void) void
fork_child(void)
{ {
int status; int status;
@@ -58,73 +61,75 @@ void fork_child (void)
* Update the file scope "self_pid" within the child process, and unlock * Update the file scope "self_pid" within the child process, and unlock
* the mutex. * the mutex.
*/ */
self_pid = getpid (); self_pid = getpid();
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock in child handler"); err_abort(status, "Unlock in child handler");
} }
/* /*
* Thread start routine, which will fork a new child process. * Thread start routine, which will fork a new child process.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
pid_t child_pid; pid_t child_pid;
int status; int status;
child_pid = fork (); child_pid = fork();
if (child_pid == (pid_t)-1) if (child_pid == (pid_t) -1)
errno_abort ("Fork"); errno_abort("Fork");
/* /*
* Lock the mutex -- without the atfork handlers, the mutex will remain * Lock the mutex -- without the atfork handlers, the mutex will remain
* locked in the child process and this lock attempt will hang (or fail * locked in the child process and this lock attempt will hang (or fail
* with EDEADLK) in the child. * with EDEADLK) in the child.
*/ */
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock in child"); err_abort(status, "Lock in child");
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock in child"); err_abort(status, "Unlock in child");
printf ("After fork: %d (%d)\n", child_pid, self_pid); printf("After fork: %d (%d)\n", child_pid, self_pid);
if (child_pid != 0) { if (child_pid != 0) {
if ((pid_t)-1 == waitpid (child_pid, (int*)0, 0)) if ((pid_t) -1 == waitpid(child_pid, (int*) 0, 0))
errno_abort ("Wait for child"); errno_abort("Wait for child");
} }
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t fork_thread; pthread_t fork_thread;
int atfork_flag = 1; int atfork_flag = 1;
int status; int status;
if (argc > 1) if (argc > 1)
atfork_flag = atoi (argv[1]); atfork_flag = atoi(argv[1]);
if (atfork_flag) { if (atfork_flag) {
status = pthread_atfork (fork_prepare, fork_parent, fork_child); status = pthread_atfork(fork_prepare, fork_parent, fork_child);
if (status != 0) if (status != 0)
err_abort (status, "Register fork handlers"); err_abort(status, "Register fork handlers");
} }
self_pid = getpid (); self_pid = getpid();
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
/* /*
* Create a thread while the mutex is locked. It will fork a process, * Create a thread while the mutex is locked. It will fork a process,
* which (without atfork handlers) will run with the mutex locked. * which (without atfork handlers) will run with the mutex locked.
*/ */
status = pthread_create (&fork_thread, NULL, thread_routine, NULL); status = pthread_create(&fork_thread, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
sleep (5); sleep(5);
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
status = pthread_join (fork_thread, NULL); status = pthread_join(fork_thread, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
return 0; return 0;
} }

View File

@@ -14,34 +14,36 @@
* is prevented by the file locks until both prompt and fgets are * is prevented by the file locks until both prompt and fgets are
* complete. * complete.
*/ */
void *prompt_routine (void *arg) void*
prompt_routine(void* arg)
{ {
char *prompt = (char*)arg; char* prompt = (char*) arg;
char *string; char* string;
int len; int len;
string = (char*)malloc (128); string = (char*) malloc(128);
if (string == NULL) if (string == NULL)
errno_abort ("Alloc string"); errno_abort("Alloc string");
flockfile (stdin); flockfile(stdin);
flockfile (stdout); flockfile(stdout);
printf (prompt); printf(prompt);
if (fgets (string, 128, stdin) == NULL) if (fgets(string, 128, stdin) == NULL)
string[0] = '\0'; string[0] = '\0';
else { else {
len = strlen (string); len = strlen(string);
if (len > 0 && string[len-1] == '\n') if (len > 0 && string[len - 1] == '\n')
string[len-1] = '\0'; string[len - 1] = '\0';
} }
funlockfile (stdout); funlockfile(stdout);
funlockfile (stdin); funlockfile(stdin);
return (void*)string; return (void*) string;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread1, thread2, thread3; pthread_t thread1, thread2, thread3;
char *string; char* string;
int status; int status;
#ifdef sun #ifdef sun
@@ -50,35 +52,32 @@ int main (int argc, char *argv[])
* that our threads can run concurrently, we need to * that our threads can run concurrently, we need to
* increase the concurrency level. * increase the concurrency level.
*/ */
DPRINTF (("Setting concurrency level to 4\n")); DPRINTF(("Setting concurrency level to 4\n"));
thr_setconcurrency (4); thr_setconcurrency(4);
#endif #endif
status = pthread_create ( status = pthread_create(&thread1, NULL, prompt_routine, "Thread 1> ");
&thread1, NULL, prompt_routine, "Thread 1> ");
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_create ( status = pthread_create(&thread2, NULL, prompt_routine, "Thread 2> ");
&thread2, NULL, prompt_routine, "Thread 2> ");
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_create ( status = pthread_create(&thread3, NULL, prompt_routine, "Thread 3> ");
&thread3, NULL, prompt_routine, "Thread 3> ");
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_join (thread1, (void**)&string); status = pthread_join(thread1, (void**) &string);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
printf ("Thread 1: \"%s\"\n", string); printf("Thread 1: \"%s\"\n", string);
free (string); free(string);
status = pthread_join (thread2, (void**)&string); status = pthread_join(thread2, (void**) &string);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
printf ("Thread 1: \"%s\"\n", string); printf("Thread 1: \"%s\"\n", string);
free (string); free(string);
status = pthread_join (thread3, (void**)&string); status = pthread_join(thread3, (void**) &string);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
printf ("Thread 1: \"%s\"\n", string); printf("Thread 1: \"%s\"\n", string);
free (string); free(string);
return 0; return 0;
} }

View File

@@ -14,29 +14,29 @@
* and dynamically allocating the buffers. * and dynamically allocating the buffers.
*/ */
#ifndef TTY_NAME_MAX #ifndef TTY_NAME_MAX
# define TTY_NAME_MAX 128 #define TTY_NAME_MAX 128
#endif #endif
#ifndef LOGIN_NAME_MAX #ifndef LOGIN_NAME_MAX
# define LOGIN_NAME_MAX 32 #define LOGIN_NAME_MAX 32
#endif #endif
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
char login_str[LOGIN_NAME_MAX]; char login_str[LOGIN_NAME_MAX];
char stdin_str[TTY_NAME_MAX]; char stdin_str[TTY_NAME_MAX];
char cterm_str[L_ctermid], *cterm_str_ptr; char cterm_str[L_ctermid], *cterm_str_ptr;
int status; int status;
status = getlogin_r (login_str, sizeof (login_str)); status = getlogin_r(login_str, sizeof(login_str));
if (status != 0) if (status != 0)
err_abort (status, "Get login"); err_abort(status, "Get login");
cterm_str_ptr = ctermid (cterm_str); cterm_str_ptr = ctermid(cterm_str);
if (cterm_str_ptr == NULL) if (cterm_str_ptr == NULL)
errno_abort ("Get cterm"); errno_abort("Get cterm");
status = ttyname_r (0, stdin_str, sizeof (stdin_str)); status = ttyname_r(0, stdin_str, sizeof(stdin_str));
if (status != 0) if (status != 0)
err_abort (status, "Get stdin"); err_abort(status, "Get stdin");
printf ("User: %s, cterm: %s, fd 0: %s\n", printf("User: %s, cterm: %s, fd 0: %s\n", login_str, cterm_str, stdin_str);
login_str, cterm_str, stdin_str);
return 0; return 0;
} }

View File

@@ -37,16 +37,17 @@
* by locking the file stream and using putchar_unlocked to * by locking the file stream and using putchar_unlocked to
* write each character individually. * write each character individually.
*/ */
void *lock_routine (void *arg) void*
lock_routine(void* arg)
{ {
char *pointer; char* pointer;
flockfile (stdout); flockfile(stdout);
for (pointer = arg; *pointer != '\0'; pointer++) { for (pointer = arg; *pointer != '\0'; pointer++) {
putchar_unlocked (*pointer); putchar_unlocked(*pointer);
sleep (1); sleep(1);
} }
funlockfile (stdout); funlockfile(stdout);
return NULL; return NULL;
} }
@@ -56,41 +57,40 @@ void *lock_routine (void *arg)
* Although the internal locking of putchar prevents file stream * Although the internal locking of putchar prevents file stream
* corruption, the writes of various threads may be interleaved. * corruption, the writes of various threads may be interleaved.
*/ */
void *unlock_routine (void *arg) void*
unlock_routine(void* arg)
{ {
char *pointer; char* pointer;
for (pointer = arg; *pointer != '\0'; pointer++) { for (pointer = arg; *pointer != '\0'; pointer++) {
putchar (*pointer); putchar(*pointer);
sleep (1); sleep(1);
} }
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread1, thread2, thread3; pthread_t thread1, thread2, thread3;
int flock_flag = 1; int flock_flag = 1;
void *(*thread_func)(void *); void* (*thread_func)(void*);
int status; int status;
if (argc > 1) if (argc > 1)
flock_flag = atoi (argv[1]); flock_flag = atoi(argv[1]);
if (flock_flag) if (flock_flag)
thread_func = lock_routine; thread_func = lock_routine;
else else
thread_func = unlock_routine; thread_func = unlock_routine;
status = pthread_create ( status = pthread_create(&thread1, NULL, thread_func, "this is thread 1\n");
&thread1, NULL, thread_func, "this is thread 1\n");
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_create ( status = pthread_create(&thread2, NULL, thread_func, "this is thread 2\n");
&thread2, NULL, thread_func, "this is thread 2\n");
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
status = pthread_create ( status = pthread_create(&thread3, NULL, thread_func, "this is thread 3\n");
&thread3, NULL, thread_func, "this is thread 3\n");
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
pthread_exit (NULL); pthread_exit(NULL);
} }

View File

@@ -8,12 +8,12 @@
* and _POSIX_SEMAPHORES features of POSIX 1003.1b-1993. It will * and _POSIX_SEMAPHORES features of POSIX 1003.1b-1993. It will
* not run (and may not compile) without them. * not run (and may not compile) without them.
*/ */
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
#include <signal.h> #include <signal.h>
#include <sys/types.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include "errors.h" #include "errors.h"
sem_t semaphore; sem_t semaphore;
@@ -21,34 +21,37 @@ sem_t semaphore;
/* /*
* Signal catching function. * Signal catching function.
*/ */
void signal_catcher (int sig) void
signal_catcher(int sig)
{ {
if (sem_post (&semaphore) == -1) if (sem_post(&semaphore) == -1)
errno_abort ("Post semaphore"); errno_abort("Post semaphore");
} }
/* /*
* Thread start routine which waits on the semaphore. * Thread start routine which waits on the semaphore.
*/ */
void *sem_waiter (void *arg) void*
sem_waiter(void* arg)
{ {
int number = (int)arg; int number = (int) arg;
int counter; int counter;
/* /*
* Each thread waits 5 times. * Each thread waits 5 times.
*/ */
for (counter = 1; counter <= 5; counter++) { for (counter = 1; counter <= 5; counter++) {
while (sem_wait (&semaphore) == -1) { while (sem_wait(&semaphore) == -1) {
if (errno != EINTR) if (errno != EINTR)
errno_abort ("Wait on semaphore"); errno_abort("Wait on semaphore");
} }
printf ("%d waking (%d)...\n", number, counter); printf("%d waking (%d)...\n", number, counter);
} }
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int thread_count, status; int thread_count, status;
struct sigevent sig_event; struct sigevent sig_event;
@@ -59,25 +62,24 @@ int main (int argc, char *argv[])
pthread_t sem_waiters[5]; pthread_t sem_waiters[5];
#if !defined(_POSIX_SEMAPHORES) || !defined(_POSIX_TIMERS) #if !defined(_POSIX_SEMAPHORES) || !defined(_POSIX_TIMERS)
# if !defined(_POSIX_SEMAPHORES) #if !defined(_POSIX_SEMAPHORES)
printf ("This system does not support POSIX semaphores\n"); printf("This system does not support POSIX semaphores\n");
# endif #endif
# if !defined(_POSIX_TIMERS) #if !defined(_POSIX_TIMERS)
printf ("This system does not support POSIX timers\n"); printf("This system does not support POSIX timers\n");
# endif #endif
return -1; return -1;
#else #else
sem_init (&semaphore, 0, 0); sem_init(&semaphore, 0, 0);
/* /*
* Create 5 threads to wait on a semaphore. * Create 5 threads to wait on a semaphore.
*/ */
for (thread_count = 0; thread_count < 5; thread_count++) { for (thread_count = 0; thread_count < 5; thread_count++) {
status = pthread_create ( status = pthread_create(
&sem_waiters[thread_count], NULL, &sem_waiters[thread_count], NULL, sem_waiter, (void*) thread_count);
sem_waiter, (void*)thread_count);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
/* /*
@@ -87,29 +89,29 @@ int main (int argc, char *argv[])
sig_event.sigev_value.sival_int = 0; sig_event.sigev_value.sival_int = 0;
sig_event.sigev_signo = SIGRTMIN; sig_event.sigev_signo = SIGRTMIN;
sig_event.sigev_notify = SIGEV_SIGNAL; sig_event.sigev_notify = SIGEV_SIGNAL;
if (timer_create (CLOCK_REALTIME, &sig_event, &timer_id) == -1) if (timer_create(CLOCK_REALTIME, &sig_event, &timer_id) == -1)
errno_abort ("Create timer"); errno_abort("Create timer");
sigemptyset (&sig_mask); sigemptyset(&sig_mask);
sigaddset (&sig_mask, SIGRTMIN); sigaddset(&sig_mask, SIGRTMIN);
sig_action.sa_handler = signal_catcher; sig_action.sa_handler = signal_catcher;
sig_action.sa_mask = sig_mask; sig_action.sa_mask = sig_mask;
sig_action.sa_flags = 0; sig_action.sa_flags = 0;
if (sigaction (SIGRTMIN, &sig_action, NULL) == -1) if (sigaction(SIGRTMIN, &sig_action, NULL) == -1)
errno_abort ("Set signal action"); errno_abort("Set signal action");
timer_val.it_interval.tv_sec = 2; timer_val.it_interval.tv_sec = 2;
timer_val.it_interval.tv_nsec = 0; timer_val.it_interval.tv_nsec = 0;
timer_val.it_value.tv_sec = 2; timer_val.it_value.tv_sec = 2;
timer_val.it_value.tv_nsec = 0; timer_val.it_value.tv_nsec = 0;
if (timer_settime (timer_id, 0, &timer_val, NULL) == -1) if (timer_settime(timer_id, 0, &timer_val, NULL) == -1)
errno_abort ("Set timer"); errno_abort("Set timer");
/* /*
* Wait for all threads to complete. * Wait for all threads to complete.
*/ */
for (thread_count = 0; thread_count < 5; thread_count++) { for (thread_count = 0; thread_count < 5; thread_count++) {
status = pthread_join (sem_waiters[thread_count], NULL); status = pthread_join(sem_waiters[thread_count], NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
} }
return 0; return 0;
#endif #endif

View File

@@ -3,11 +3,11 @@
* *
* Demonstrate use of semaphores for synchronization. * Demonstrate use of semaphores for synchronization.
*/ */
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
#include <signal.h> #include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "errors.h" #include "errors.h"
sem_t semaphore; sem_t semaphore;
@@ -15,43 +15,44 @@ sem_t semaphore;
/* /*
* Thread start routine to wait on a semaphore. * Thread start routine to wait on a semaphore.
*/ */
void *sem_waiter (void *arg) void*
sem_waiter(void* arg)
{ {
long num = (long)arg; long num = (long) arg;
printf ("Thread %d waiting\n", num); printf("Thread %d waiting\n", num);
if (sem_wait (&semaphore) == -1) if (sem_wait(&semaphore) == -1)
errno_abort ("Wait on semaphore"); errno_abort("Wait on semaphore");
printf ("Thread %d resuming\n", num); printf("Thread %d resuming\n", num);
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int thread_count; int thread_count;
pthread_t sem_waiters[5]; pthread_t sem_waiters[5];
int status; int status;
#if !defined(_POSIX_SEMAPHORES) #if !defined(_POSIX_SEMAPHORES)
printf ("This system does not support POSIX semaphores\n"); printf("This system does not support POSIX semaphores\n");
return -1; return -1;
#else #else
if (sem_init (&semaphore, 0, 0) == -1) if (sem_init(&semaphore, 0, 0) == -1)
errno_abort ("Init semaphore"); errno_abort("Init semaphore");
/* /*
* Create 5 threads to wait concurrently on the semaphore. * Create 5 threads to wait concurrently on the semaphore.
*/ */
for (thread_count = 0; thread_count < 5; thread_count++) { for (thread_count = 0; thread_count < 5; thread_count++) {
status = pthread_create ( status = pthread_create(
&sem_waiters[thread_count], NULL, &sem_waiters[thread_count], NULL, sem_waiter, (void*) thread_count);
sem_waiter, (void*)thread_count);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
sleep (2); sleep(2);
/* /*
* "Broadcast" the semaphore by repeatedly posting until the * "Broadcast" the semaphore by repeatedly posting until the
@@ -60,22 +61,22 @@ int main (int argc, char *argv[])
while (1) { while (1) {
int sem_value; int sem_value;
if (sem_getvalue (&semaphore, &sem_value) == -1) if (sem_getvalue(&semaphore, &sem_value) == -1)
errno_abort ("Get semaphore value"); errno_abort("Get semaphore value");
if (sem_value >= 0) if (sem_value >= 0)
break; break;
printf ("Posting from main: %d\n", sem_value); printf("Posting from main: %d\n", sem_value);
if (sem_post (&semaphore) == -1) if (sem_post(&semaphore) == -1)
errno_abort ("Post semaphore"); errno_abort("Post semaphore");
} }
/* /*
* Wait for all threads to complete. * Wait for all threads to complete.
*/ */
for (thread_count = 0; thread_count < 5; thread_count++) { for (thread_count = 0; thread_count < 5; thread_count++) {
status = pthread_join (sem_waiters[thread_count], NULL); status = pthread_join(sem_waiters[thread_count], NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
} }
return 0; return 0;
#endif #endif

View File

@@ -29,23 +29,23 @@ int counter = 0;
* be awakened, and will terminate the program. * be awakened, and will terminate the program.
*/ */
void void
timer_thread (void *arg) timer_thread(void* arg)
{ {
int status; int status;
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
if (++counter >= 5) { if (++counter >= 5) {
status = pthread_cond_signal (&cond); status = pthread_cond_signal(&cond);
if (status != 0) if (status != 0)
err_abort (status, "Signal condition"); err_abort(status, "Signal condition");
} }
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
printf ("Timer %d\n", counter); printf("Timer %d\n", counter);
} }
main() main()
@@ -55,8 +55,7 @@ main()
struct sigevent se; struct sigevent se;
#ifdef sun #ifdef sun
fprintf ( fprintf(stderr,
stderr,
"This program cannot compile on Solaris 2.5.\n" "This program cannot compile on Solaris 2.5.\n"
"To build and run on Solaris 2.6, remove the\n" "To build and run on Solaris 2.6, remove the\n"
"\"#ifdef sun\" block in main().\n"); "\"#ifdef sun\" block in main().\n");
@@ -78,28 +77,27 @@ main()
ts.it_interval.tv_sec = 5; ts.it_interval.tv_sec = 5;
ts.it_interval.tv_nsec = 0; ts.it_interval.tv_nsec = 0;
DPRINTF (("Creating timer\n")); DPRINTF(("Creating timer\n"));
status = timer_create(CLOCK_REALTIME, &se, &timer_id); status = timer_create(CLOCK_REALTIME, &se, &timer_id);
if (status == -1) if (status == -1)
errno_abort ("Create timer"); errno_abort("Create timer");
DPRINTF (( DPRINTF(("Setting timer %d for 5-second expiration...\n", timer_id));
"Setting timer %d for 5-second expiration...\n", timer_id));
status = timer_settime(timer_id, 0, &ts, 0); status = timer_settime(timer_id, 0, &ts, 0);
if (status == -1) if (status == -1)
errno_abort ("Set timer"); errno_abort("Set timer");
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
while (counter < 5) { while (counter < 5) {
status = pthread_cond_wait (&cond, &mutex); status = pthread_cond_wait(&cond, &mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait on condition"); err_abort(status, "Wait on condition");
} }
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
#endif /* Sun */ #endif /* Sun */
return 0; return 0;

View File

@@ -4,10 +4,10 @@
* Demonstrate use of sigwait() to synchronously handle * Demonstrate use of sigwait() to synchronously handle
* asynchrnous signals within a threaded program. * asynchrnous signals within a threaded program.
*/ */
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "errors.h" #include "errors.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -20,27 +20,28 @@ sigset_t signal_set;
* the "interrupted" flag (the main thread's wait predicate) and * the "interrupted" flag (the main thread's wait predicate) and
* signal a condition variable. The main thread will exit. * signal a condition variable. The main thread will exit.
*/ */
void *signal_waiter (void *arg) void*
signal_waiter(void* arg)
{ {
int sig_number; int sig_number;
int signal_count = 0; int signal_count = 0;
int status; int status;
while (1) { while (1) {
sigwait (&signal_set, &sig_number); sigwait(&signal_set, &sig_number);
if (sig_number == SIGINT) { if (sig_number == SIGINT) {
printf ("Got SIGINT (%d of 5)\n", signal_count+1); printf("Got SIGINT (%d of 5)\n", signal_count + 1);
if (++signal_count >= 5) { if (++signal_count >= 5) {
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
interrupted = 1; interrupted = 1;
status = pthread_cond_signal (&cond); status = pthread_cond_signal(&cond);
if (status != 0) if (status != 0)
err_abort (status, "Signal condition"); err_abort(status, "Signal condition");
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
break; break;
} }
} }
@@ -48,7 +49,8 @@ void *signal_waiter (void *arg)
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t signal_thread_id; pthread_t signal_thread_id;
int status; int status;
@@ -64,35 +66,34 @@ int main (int argc, char *argv[])
* while the sigwaiter is not blocked in sigwait might be * while the sigwaiter is not blocked in sigwait might be
* delivered to another thread. * delivered to another thread.
*/ */
sigemptyset (&signal_set); sigemptyset(&signal_set);
sigaddset (&signal_set, SIGINT); sigaddset(&signal_set, SIGINT);
status = pthread_sigmask (SIG_BLOCK, &signal_set, NULL); status = pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Set signal mask"); err_abort(status, "Set signal mask");
/* /*
* Create the sigwait thread. * Create the sigwait thread.
*/ */
status = pthread_create (&signal_thread_id, NULL, status = pthread_create(&signal_thread_id, NULL, signal_waiter, NULL);
signal_waiter, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create sigwaiter"); err_abort(status, "Create sigwaiter");
/* /*
* Wait for the sigwait thread to receive SIGINT and signal * Wait for the sigwait thread to receive SIGINT and signal
* the condition variable. * the condition variable.
*/ */
status = pthread_mutex_lock (&mutex); status = pthread_mutex_lock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Lock mutex"); err_abort(status, "Lock mutex");
while (!interrupted) { while (!interrupted) {
status = pthread_cond_wait (&cond, &mutex); status = pthread_cond_wait(&cond, &mutex);
if (status != 0) if (status != 0)
err_abort (status, "Wait for interrupt"); err_abort(status, "Wait for interrupt");
} }
status = pthread_mutex_unlock (&mutex); status = pthread_mutex_unlock(&mutex);
if (status != 0) if (status != 0)
err_abort (status, "Unlock mutex"); err_abort(status, "Unlock mutex");
printf ("Main terminating with SIGINT\n"); printf("Main terminating with SIGINT\n");
return 0; return 0;
} }

View File

@@ -44,17 +44,17 @@ int inited = 0;
* receiving SIGUSR2 (resume). * receiving SIGUSR2 (resume).
*/ */
void void
suspend_signal_handler (int sig) suspend_signal_handler(int sig)
{ {
sigset_t signal_set; sigset_t signal_set;
/* /*
* Block all signals except SIGUSR2 while suspended. * Block all signals except SIGUSR2 while suspended.
*/ */
sigfillset (&signal_set); sigfillset(&signal_set);
sigdelset (&signal_set, SIGUSR2); sigdelset(&signal_set, SIGUSR2);
sentinel = 1; sentinel = 1;
sigsuspend (&signal_set); sigsuspend(&signal_set);
/* /*
* Once I'm here, I've been resumed, and the resume signal * Once I'm here, I've been resumed, and the resume signal
@@ -69,7 +69,7 @@ suspend_signal_handler (int sig)
* to cause sigsuspend() to return. * to cause sigsuspend() to return.
*/ */
void void
resume_signal_handler (int sig) resume_signal_handler(int sig)
{ {
return; return;
} }
@@ -79,7 +79,7 @@ resume_signal_handler (int sig)
* (called by pthread_once). * (called by pthread_once).
*/ */
void void
suspend_init_routine (void) suspend_init_routine(void)
{ {
int status; int status;
struct sigaction sigusr1, sigusr2; struct sigaction sigusr1, sigusr2;
@@ -89,7 +89,7 @@ suspend_init_routine (void)
* to guarentee idempotency * to guarentee idempotency
*/ */
bottom = 10; bottom = 10;
array = (pthread_t*) calloc (bottom, sizeof (pthread_t)); array = (pthread_t*) calloc(bottom, sizeof(pthread_t));
/* /*
* Install the signal handlers for suspend/resume. * Install the signal handlers for suspend/resume.
@@ -97,18 +97,18 @@ suspend_init_routine (void)
sigusr1.sa_flags = 0; sigusr1.sa_flags = 0;
sigusr1.sa_handler = suspend_signal_handler; sigusr1.sa_handler = suspend_signal_handler;
sigemptyset (&sigusr1.sa_mask); sigemptyset(&sigusr1.sa_mask);
sigusr2.sa_flags = 0; sigusr2.sa_flags = 0;
sigusr2.sa_handler = resume_signal_handler; sigusr2.sa_handler = resume_signal_handler;
sigusr2.sa_mask = sigusr1.sa_mask; sigusr2.sa_mask = sigusr1.sa_mask;
status = sigaction (SIGUSR1, &sigusr1, NULL); status = sigaction(SIGUSR1, &sigusr1, NULL);
if (status == -1) if (status == -1)
errno_abort ("Installing suspend handler"); errno_abort("Installing suspend handler");
status = sigaction (SIGUSR2, &sigusr2, NULL); status = sigaction(SIGUSR2, &sigusr2, NULL);
if (status == -1) if (status == -1)
errno_abort ("Installing resume handler"); errno_abort("Installing resume handler");
inited = 1; inited = 1;
return; return;
@@ -123,7 +123,7 @@ suspend_init_routine (void)
* call will cause it to resume execution. * call will cause it to resume execution.
*/ */
int int
thd_suspend (pthread_t target_thread) thd_suspend(pthread_t target_thread)
{ {
int status; int status;
int i = 0; int i = 0;
@@ -132,14 +132,14 @@ thd_suspend (pthread_t target_thread)
* The first call to thd_suspend will initialize the * The first call to thd_suspend will initialize the
* package. * package.
*/ */
status = pthread_once (&once, suspend_init_routine); status = pthread_once(&once, suspend_init_routine);
if (status != 0) if (status != 0)
return status; return status;
/* /*
* Serialize access to suspend, makes life easier * Serialize access to suspend, makes life easier
*/ */
status = pthread_mutex_lock (&mut); status = pthread_mutex_lock(&mut);
if (status != 0) if (status != 0)
return status; return status;
@@ -151,7 +151,7 @@ thd_suspend (pthread_t target_thread)
*/ */
while (i < bottom) while (i < bottom)
if (array[i++] == target_thread) { if (array[i++] == target_thread) {
status = pthread_mutex_unlock (&mut); status = pthread_mutex_unlock(&mut);
return status; return status;
} }
@@ -161,14 +161,12 @@ thd_suspend (pthread_t target_thread)
* the end, realloc the array for more space. * the end, realloc the array for more space.
*/ */
i = 0; i = 0;
while (array[i] != 0) while (array[i] != 0) i++;
i++;
if (i == bottom) { if (i == bottom) {
array = (pthread_t*) realloc ( array = (pthread_t*) realloc(array, (++bottom * sizeof(pthread_t)));
array, (++bottom * sizeof (pthread_t)));
if (array == NULL) { if (array == NULL) {
pthread_mutex_unlock (&mut); pthread_mutex_unlock(&mut);
return errno; return errno;
} }
@@ -179,21 +177,20 @@ thd_suspend (pthread_t target_thread)
* Clear the sentinel and signal the thread to suspend. * Clear the sentinel and signal the thread to suspend.
*/ */
sentinel = 0; sentinel = 0;
status = pthread_kill (target_thread, SIGUSR1); status = pthread_kill(target_thread, SIGUSR1);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&mut); pthread_mutex_unlock(&mut);
return status; return status;
} }
/* /*
* Wait for the sentinel to change. * Wait for the sentinel to change.
*/ */
while (sentinel == 0) while (sentinel == 0) sched_yield();
sched_yield ();
array[i] = target_thread; array[i] = target_thread;
status = pthread_mutex_unlock (&mut); status = pthread_mutex_unlock(&mut);
return status; return status;
} }
@@ -203,7 +200,7 @@ thd_suspend (pthread_t target_thread)
* target thread isn't suspended, return with success. * target thread isn't suspended, return with success.
*/ */
int int
thd_continue (pthread_t target_thread) thd_continue(pthread_t target_thread)
{ {
int status; int status;
int i = 0; int i = 0;
@@ -211,7 +208,7 @@ thd_continue (pthread_t target_thread)
/* /*
* Serialize access to suspend, makes life easier * Serialize access to suspend, makes life easier
*/ */
status = pthread_mutex_lock (&mut); status = pthread_mutex_lock(&mut);
if (status != 0) if (status != 0)
return status; return status;
@@ -220,7 +217,7 @@ thd_continue (pthread_t target_thread)
* it couldn't have been suspended! * it couldn't have been suspended!
*/ */
if (!inited) { if (!inited) {
status = pthread_mutex_unlock (&mut); status = pthread_mutex_unlock(&mut);
return status; return status;
} }
@@ -229,11 +226,10 @@ thd_continue (pthread_t target_thread)
* hasn't been suspended (or it has already been resumed) and * hasn't been suspended (or it has already been resumed) and
* we can just carry on. * we can just carry on.
*/ */
while (array[i] != target_thread && i < bottom) while (array[i] != target_thread && i < bottom) i++;
i++;
if (i >= bottom) { if (i >= bottom) {
pthread_mutex_unlock (&mut); pthread_mutex_unlock(&mut);
return 0; return 0;
} }
@@ -241,21 +237,21 @@ thd_continue (pthread_t target_thread)
* Signal the thread to continue, and remove the thread from * Signal the thread to continue, and remove the thread from
* the suspended array. * the suspended array.
*/ */
status = pthread_kill (target_thread, SIGUSR2); status = pthread_kill(target_thread, SIGUSR2);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&mut); pthread_mutex_unlock(&mut);
return status; return status;
} }
array[i] = 0; /* Clear array element */ array[i] = 0; /* Clear array element */
status = pthread_mutex_unlock (&mut); status = pthread_mutex_unlock(&mut);
return status; return status;
} }
static void * static void*
thread_routine (void *arg) thread_routine(void* arg)
{ {
int number = (int)arg; int number = (int) arg;
int status; int status;
int i; int i;
char buffer[128]; char buffer[128];
@@ -266,77 +262,73 @@ thread_routine (void *arg)
* a progress report. * a progress report.
*/ */
if (i % 2000 == 0) { if (i % 2000 == 0) {
sprintf ( sprintf(buffer, "Thread %02d: %d\n", number, i);
buffer, "Thread %02d: %d\n", write(1, buffer, strlen(buffer));
number, i);
write (1, buffer, strlen (buffer));
} }
sched_yield (); sched_yield();
} }
return (void *)0; return (void*) 0;
} }
int int
main (int argc, char *argv[]) main(int argc, char* argv[])
{ {
pthread_t threads[THREAD_COUNT]; pthread_t threads[THREAD_COUNT];
pthread_attr_t detach; pthread_attr_t detach;
int status; int status;
void *result; void* result;
int i; int i;
status = pthread_attr_init (&detach); status = pthread_attr_init(&detach);
if (status != 0) if (status != 0)
err_abort (status, "Init attributes object"); err_abort(status, "Init attributes object");
status = pthread_attr_setdetachstate ( status = pthread_attr_setdetachstate(&detach, PTHREAD_CREATE_DETACHED);
&detach, PTHREAD_CREATE_DETACHED);
if (status != 0) if (status != 0)
err_abort (status, "Set create-detached"); err_abort(status, "Set create-detached");
for (i = 0; i< THREAD_COUNT; i++) { for (i = 0; i < THREAD_COUNT; i++) {
status = pthread_create ( status = pthread_create(&threads[i], &detach, thread_routine, (void*) i);
&threads[i], &detach, thread_routine, (void *)i);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
sleep (2); sleep(2);
for (i = 0; i < THREAD_COUNT/2; i++) { for (i = 0; i < THREAD_COUNT / 2; i++) {
printf ("Suspending thread %d.\n", i); printf("Suspending thread %d.\n", i);
status = thd_suspend (threads[i]); status = thd_suspend(threads[i]);
if (status != 0) if (status != 0)
err_abort (status, "Suspend thread"); err_abort(status, "Suspend thread");
} }
printf ("Sleeping ...\n"); printf("Sleeping ...\n");
sleep (2); sleep(2);
for (i = 0; i < THREAD_COUNT/2; i++) { for (i = 0; i < THREAD_COUNT / 2; i++) {
printf ("Continuing thread %d.\n", i); printf("Continuing thread %d.\n", i);
status = thd_continue (threads[i]); status = thd_continue(threads[i]);
if (status != 0) if (status != 0)
err_abort (status, "Suspend thread"); err_abort(status, "Suspend thread");
} }
for (i = THREAD_COUNT/2; i < THREAD_COUNT; i++) { for (i = THREAD_COUNT / 2; i < THREAD_COUNT; i++) {
printf ("Suspending thread %d.\n", i); printf("Suspending thread %d.\n", i);
status = thd_suspend (threads[i]); status = thd_suspend(threads[i]);
if (status != 0) if (status != 0)
err_abort (status, "Suspend thread"); err_abort(status, "Suspend thread");
} }
printf ("Sleeping ...\n"); printf("Sleeping ...\n");
sleep (2); sleep(2);
for (i = THREAD_COUNT/2; i < THREAD_COUNT; i++) { for (i = THREAD_COUNT / 2; i < THREAD_COUNT; i++) {
printf ("Continuing thread %d.\n", i); printf("Continuing thread %d.\n", i);
status = thd_continue (threads[i]); status = thd_continue(threads[i]);
if (status != 0) if (status != 0)
err_abort (status, "Continue thread"); err_abort(status, "Continue thread");
} }
pthread_exit (NULL); /* Let threads finish */ pthread_exit(NULL); /* Let threads finish */
} }

View File

@@ -20,25 +20,26 @@
* to do something in a serial region before entering another * to do something in a serial region before entering another
* parallel section of code. * parallel section of code.
*/ */
#include "barrier.h"
#include <pthread.h> #include <pthread.h>
#include "errors.h" #include "errors.h"
#include "barrier.h"
/* /*
* Initialize a barrier for use. * Initialize a barrier for use.
*/ */
int barrier_init (barrier_t *barrier, int count) int
barrier_init(barrier_t* barrier, int count)
{ {
int status; int status;
barrier->threshold = barrier->counter = count; barrier->threshold = barrier->counter = count;
barrier->cycle = 0; barrier->cycle = 0;
status = pthread_mutex_init (&barrier->mutex, NULL); status = pthread_mutex_init(&barrier->mutex, NULL);
if (status != 0) if (status != 0)
return status; return status;
status = pthread_cond_init (&barrier->cv, NULL); status = pthread_cond_init(&barrier->cv, NULL);
if (status != 0) { if (status != 0) {
pthread_mutex_destroy (&barrier->mutex); pthread_mutex_destroy(&barrier->mutex);
return status; return status;
} }
barrier->valid = BARRIER_VALID; barrier->valid = BARRIER_VALID;
@@ -48,14 +49,15 @@ int barrier_init (barrier_t *barrier, int count)
/* /*
* Destroy a barrier when done using it. * Destroy a barrier when done using it.
*/ */
int barrier_destroy (barrier_t *barrier) int
barrier_destroy(barrier_t* barrier)
{ {
int status, status2; int status, status2;
if (barrier->valid != BARRIER_VALID) if (barrier->valid != BARRIER_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&barrier->mutex); status = pthread_mutex_lock(&barrier->mutex);
if (status != 0) if (status != 0)
return status; return status;
@@ -64,12 +66,12 @@ int barrier_destroy (barrier_t *barrier)
* "BUSY" if so. * "BUSY" if so.
*/ */
if (barrier->counter != barrier->threshold) { if (barrier->counter != barrier->threshold) {
pthread_mutex_unlock (&barrier->mutex); pthread_mutex_unlock(&barrier->mutex);
return EBUSY; return EBUSY;
} }
barrier->valid = 0; barrier->valid = 0;
status = pthread_mutex_unlock (&barrier->mutex); status = pthread_mutex_unlock(&barrier->mutex);
if (status != 0) if (status != 0)
return status; return status;
@@ -77,8 +79,8 @@ int barrier_destroy (barrier_t *barrier)
* If unable to destroy either 1003.1c synchronization * If unable to destroy either 1003.1c synchronization
* object, return the error status. * object, return the error status.
*/ */
status = pthread_mutex_destroy (&barrier->mutex); status = pthread_mutex_destroy(&barrier->mutex);
status2 = pthread_cond_destroy (&barrier->cv); status2 = pthread_cond_destroy(&barrier->cv);
return (status == 0 ? status : status2); return (status == 0 ? status : status2);
} }
@@ -87,14 +89,15 @@ int barrier_destroy (barrier_t *barrier)
* the count (of remaining members) reaches 0, broadcast to wake * the count (of remaining members) reaches 0, broadcast to wake
* all threads waiting. * all threads waiting.
*/ */
int barrier_wait (barrier_t *barrier) int
barrier_wait(barrier_t* barrier)
{ {
int status, cancel, tmp, cycle; int status, cancel, tmp, cycle;
if (barrier->valid != BARRIER_VALID) if (barrier->valid != BARRIER_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&barrier->mutex); status = pthread_mutex_lock(&barrier->mutex);
if (status != 0) if (status != 0)
return status; return status;
@@ -103,7 +106,7 @@ int barrier_wait (barrier_t *barrier)
if (--barrier->counter == 0) { if (--barrier->counter == 0) {
barrier->cycle = !barrier->cycle; barrier->cycle = !barrier->cycle;
barrier->counter = barrier->threshold; barrier->counter = barrier->threshold;
status = pthread_cond_broadcast (&barrier->cv); status = pthread_cond_broadcast(&barrier->cv);
/* /*
* The last thread into the barrier will return status * The last thread into the barrier will return status
* -1 rather than 0, so that it can be used to perform * -1 rather than 0, so that it can be used to perform
@@ -111,12 +114,13 @@ int barrier_wait (barrier_t *barrier)
*/ */
if (status == 0) if (status == 0)
status = -1; status = -1;
} else { }
else {
/* /*
* Wait with cancellation disabled, because barrier_wait * Wait with cancellation disabled, because barrier_wait
* should not be a cancellation point. * should not be a cancellation point.
*/ */
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &cancel); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
/* /*
* Wait until the barrier's cycle changes, which means * Wait until the barrier's cycle changes, which means
@@ -124,12 +128,12 @@ int barrier_wait (barrier_t *barrier)
* anymore. * anymore.
*/ */
while (cycle == barrier->cycle) { while (cycle == barrier->cycle) {
status = pthread_cond_wait ( status = pthread_cond_wait(&barrier->cv, &barrier->mutex);
&barrier->cv, &barrier->mutex); if (status != 0)
if (status != 0) break; break;
} }
pthread_setcancelstate (cancel, &tmp); pthread_setcancelstate(cancel, &tmp);
} }
/* /*
* Ignore an error in unlocking. It shouldn't happen, and * Ignore an error in unlocking. It shouldn't happen, and
@@ -139,6 +143,6 @@ int barrier_wait (barrier_t *barrier)
* to use the barrier *will* return an error, or hang, due * to use the barrier *will* return an error, or hang, due
* to whatever happened to the mutex. * to whatever happened to the mutex.
*/ */
pthread_mutex_unlock (&barrier->mutex); pthread_mutex_unlock(&barrier->mutex);
return status; /* error, -1 for waker, or 0 */ return status; /* error, -1 for waker, or 0 */
} }

View File

@@ -31,12 +31,14 @@ typedef struct barrier_tag {
* Support static initialization of barriers * Support static initialization of barriers
*/ */
#define BARRIER_INITIALIZER(cnt) \ #define BARRIER_INITIALIZER(cnt) \
{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, \ { \
BARRIER_VALID, cnt, cnt, 0} PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, BARRIER_VALID, cnt, \
cnt, 0 \
}
/* /*
* Define barrier functions * Define barrier functions
*/ */
extern int barrier_init (barrier_t *barrier, int count); extern int barrier_init(barrier_t* barrier, int count);
extern int barrier_destroy (barrier_t *barrier); extern int barrier_destroy(barrier_t* barrier);
extern int barrier_wait (barrier_t *barrier); extern int barrier_wait(barrier_t* barrier);

View File

@@ -21,7 +21,7 @@ typedef struct thread_tag {
int number; int number;
int increment; int increment;
int array[ARRAY]; int array[ARRAY];
} thread_t; } thread_t;
barrier_t barrier; barrier_t barrier;
thread_t thread[THREADS]; thread_t thread[THREADS];
@@ -29,18 +29,19 @@ thread_t thread[THREADS];
/* /*
* Start routine for threads. * Start routine for threads.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
thread_t *self = (thread_t*)arg; /* Thread's thread_t */ thread_t* self = (thread_t*) arg; /* Thread's thread_t */
int in_loop, out_loop, count, status; int in_loop, out_loop, count, status;
/* /*
* Loop through OUTLOOPS barrier cycles. * Loop through OUTLOOPS barrier cycles.
*/ */
for (out_loop = 0; out_loop < OUTLOOPS; out_loop++) { for (out_loop = 0; out_loop < OUTLOOPS; out_loop++) {
status = barrier_wait (&barrier); status = barrier_wait(&barrier);
if (status > 0) if (status > 0)
err_abort (status, "Wait on barrier"); err_abort(status, "Wait on barrier");
/* /*
* This inner loop just adds a value to each element in * This inner loop just adds a value to each element in
@@ -50,9 +51,9 @@ void *thread_routine (void *arg)
for (count = 0; count < ARRAY; count++) for (count = 0; count < ARRAY; count++)
self->array[count] += self->increment; self->array[count] += self->increment;
status = barrier_wait (&barrier); status = barrier_wait(&barrier);
if (status > 0) if (status > 0)
err_abort (status, "Wait on barrier"); err_abort(status, "Wait on barrier");
/* /*
* The barrier causes one thread to return with the * The barrier causes one thread to return with the
@@ -69,12 +70,13 @@ void *thread_routine (void *arg)
return NULL; return NULL;
} }
int main (int arg, char *argv[]) int
main(int arg, char* argv[])
{ {
int thread_count, array_count; int thread_count, array_count;
int status; int status;
barrier_init (&barrier, THREADS); barrier_init(&barrier, THREADS);
/* /*
* Create a set of threads that will use the barrier. * Create a set of threads that will use the barrier.
@@ -86,30 +88,32 @@ int main (int arg, char *argv[])
for (array_count = 0; array_count < ARRAY; array_count++) for (array_count = 0; array_count < ARRAY; array_count++)
thread[thread_count].array[array_count] = array_count + 1; thread[thread_count].array[array_count] = array_count + 1;
status = pthread_create (&thread[thread_count].thread_id, status = pthread_create(&thread[thread_count].thread_id,
NULL, thread_routine, (void*)&thread[thread_count]); NULL,
thread_routine,
(void*) &thread[thread_count]);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
/* /*
* Now join with each of the threads. * Now join with each of the threads.
*/ */
for (thread_count = 0; thread_count < THREADS; thread_count++) { for (thread_count = 0; thread_count < THREADS; thread_count++) {
status = pthread_join (thread[thread_count].thread_id, NULL); status = pthread_join(thread[thread_count].thread_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
printf ("%02d: (%d) ", thread_count, thread[thread_count].increment); printf("%02d: (%d) ", thread_count, thread[thread_count].increment);
for (array_count = 0; array_count < ARRAY; array_count++) for (array_count = 0; array_count < ARRAY; array_count++)
printf ("%010u ", thread[thread_count].array[array_count]); printf("%010u ", thread[thread_count].array[array_count]);
printf ("\n"); printf("\n");
} }
/* /*
* To be thorough, destroy the barrier. * To be thorough, destroy the barrier.
*/ */
barrier_destroy (&barrier); barrier_destroy(&barrier);
return 0; return 0;
} }

View File

@@ -21,34 +21,35 @@
* lock. rwl_writetrylock() attempts to lock a read-write lock * lock. rwl_writetrylock() attempts to lock a read-write lock
* for write access, and returns EBUSY instead of blocking. * for write access, and returns EBUSY instead of blocking.
*/ */
#include "rwlock.h"
#include <pthread.h> #include <pthread.h>
#include "errors.h" #include "errors.h"
#include "rwlock.h"
/* /*
* Initialize a read-write lock * Initialize a read-write lock
*/ */
int rwl_init (rwlock_t *rwl) int
rwl_init(rwlock_t* rwl)
{ {
int status; int status;
rwl->r_active = 0; rwl->r_active = 0;
rwl->r_wait = rwl->w_wait = 0; rwl->r_wait = rwl->w_wait = 0;
rwl->w_active = 0; rwl->w_active = 0;
status = pthread_mutex_init (&rwl->mutex, NULL); status = pthread_mutex_init(&rwl->mutex, NULL);
if (status != 0) if (status != 0)
return status; return status;
status = pthread_cond_init (&rwl->read, NULL); status = pthread_cond_init(&rwl->read, NULL);
if (status != 0) { if (status != 0) {
/* if unable to create read CV, destroy mutex */ /* if unable to create read CV, destroy mutex */
pthread_mutex_destroy (&rwl->mutex); pthread_mutex_destroy(&rwl->mutex);
return status; return status;
} }
status = pthread_cond_init (&rwl->write, NULL); status = pthread_cond_init(&rwl->write, NULL);
if (status != 0) { if (status != 0) {
/* if unable to create write CV, destroy read CV and mutex */ /* if unable to create write CV, destroy read CV and mutex */
pthread_cond_destroy (&rwl->read); pthread_cond_destroy(&rwl->read);
pthread_mutex_destroy (&rwl->mutex); pthread_mutex_destroy(&rwl->mutex);
return status; return status;
} }
rwl->valid = RWLOCK_VALID; rwl->valid = RWLOCK_VALID;
@@ -58,13 +59,14 @@ int rwl_init (rwlock_t *rwl)
/* /*
* Destroy a read-write lock * Destroy a read-write lock
*/ */
int rwl_destroy (rwlock_t *rwl) int
rwl_destroy(rwlock_t* rwl)
{ {
int status, status1, status2; int status, status1, status2;
if (rwl->valid != RWLOCK_VALID) if (rwl->valid != RWLOCK_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&rwl->mutex); status = pthread_mutex_lock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
@@ -73,7 +75,7 @@ int rwl_destroy (rwlock_t *rwl)
* so. * so.
*/ */
if (rwl->r_active > 0 || rwl->w_active) { if (rwl->r_active > 0 || rwl->w_active) {
pthread_mutex_unlock (&rwl->mutex); pthread_mutex_unlock(&rwl->mutex);
return EBUSY; return EBUSY;
} }
@@ -82,17 +84,17 @@ int rwl_destroy (rwlock_t *rwl)
* EBUSY if so. * EBUSY if so.
*/ */
if (rwl->r_wait != 0 || rwl->w_wait != 0) { if (rwl->r_wait != 0 || rwl->w_wait != 0) {
pthread_mutex_unlock (&rwl->mutex); pthread_mutex_unlock(&rwl->mutex);
return EBUSY; return EBUSY;
} }
rwl->valid = 0; rwl->valid = 0;
status = pthread_mutex_unlock (&rwl->mutex); status = pthread_mutex_unlock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
status = pthread_mutex_destroy (&rwl->mutex); status = pthread_mutex_destroy(&rwl->mutex);
status1 = pthread_cond_destroy (&rwl->read); status1 = pthread_cond_destroy(&rwl->read);
status2 = pthread_cond_destroy (&rwl->write); status2 = pthread_cond_destroy(&rwl->write);
return (status == 0 ? status : (status1 == 0 ? status1 : status2)); return (status == 0 ? status : (status1 == 0 ? status1 : status2));
} }
@@ -103,40 +105,42 @@ int rwl_destroy (rwlock_t *rwl)
* Simply record that the thread is no longer waiting, * Simply record that the thread is no longer waiting,
* and unlock the mutex. * and unlock the mutex.
*/ */
static void rwl_readcleanup (void *arg) static void
rwl_readcleanup(void* arg)
{ {
rwlock_t *rwl = (rwlock_t *)arg; rwlock_t* rwl = (rwlock_t*) arg;
rwl->r_wait--; rwl->r_wait--;
pthread_mutex_unlock (&rwl->mutex); pthread_mutex_unlock(&rwl->mutex);
} }
/* /*
* Lock a read-write lock for read access. * Lock a read-write lock for read access.
*/ */
int rwl_readlock (rwlock_t *rwl) int
rwl_readlock(rwlock_t* rwl)
{ {
int status; int status;
if (rwl->valid != RWLOCK_VALID) if (rwl->valid != RWLOCK_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&rwl->mutex); status = pthread_mutex_lock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
if (rwl->w_active) { if (rwl->w_active) {
rwl->r_wait++; rwl->r_wait++;
pthread_cleanup_push (rwl_readcleanup, (void*)rwl); pthread_cleanup_push(rwl_readcleanup, (void*) rwl);
while (rwl->w_active) { while (rwl->w_active) {
status = pthread_cond_wait (&rwl->read, &rwl->mutex); status = pthread_cond_wait(&rwl->read, &rwl->mutex);
if (status != 0) if (status != 0)
break; break;
} }
pthread_cleanup_pop (0); pthread_cleanup_pop(0);
rwl->r_wait--; rwl->r_wait--;
} }
if (status == 0) if (status == 0)
rwl->r_active++; rwl->r_active++;
pthread_mutex_unlock (&rwl->mutex); pthread_mutex_unlock(&rwl->mutex);
return status; return status;
} }
@@ -144,39 +148,41 @@ int rwl_readlock (rwlock_t *rwl)
* Attempt to lock a read-write lock for read access (don't * Attempt to lock a read-write lock for read access (don't
* block if unavailable). * block if unavailable).
*/ */
int rwl_readtrylock (rwlock_t *rwl) int
rwl_readtrylock(rwlock_t* rwl)
{ {
int status, status2; int status, status2;
if (rwl->valid != RWLOCK_VALID) if (rwl->valid != RWLOCK_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&rwl->mutex); status = pthread_mutex_lock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
if (rwl->w_active) if (rwl->w_active)
status = EBUSY; status = EBUSY;
else else
rwl->r_active++; rwl->r_active++;
status2 = pthread_mutex_unlock (&rwl->mutex); status2 = pthread_mutex_unlock(&rwl->mutex);
return (status2 != 0 ? status2 : status); return (status2 != 0 ? status2 : status);
} }
/* /*
* Unlock a read-write lock from read access. * Unlock a read-write lock from read access.
*/ */
int rwl_readunlock (rwlock_t *rwl) int
rwl_readunlock(rwlock_t* rwl)
{ {
int status, status2; int status, status2;
if (rwl->valid != RWLOCK_VALID) if (rwl->valid != RWLOCK_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&rwl->mutex); status = pthread_mutex_lock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
rwl->r_active--; rwl->r_active--;
if (rwl->r_active == 0 && rwl->w_wait > 0) if (rwl->r_active == 0 && rwl->w_wait > 0)
status = pthread_cond_signal (&rwl->write); status = pthread_cond_signal(&rwl->write);
status2 = pthread_mutex_unlock (&rwl->mutex); status2 = pthread_mutex_unlock(&rwl->mutex);
return (status2 == 0 ? status : status2); return (status2 == 0 ? status : status2);
} }
@@ -187,40 +193,42 @@ int rwl_readunlock (rwlock_t *rwl)
* Simply record that the thread is no longer waiting, * Simply record that the thread is no longer waiting,
* and unlock the mutex. * and unlock the mutex.
*/ */
static void rwl_writecleanup (void *arg) static void
rwl_writecleanup(void* arg)
{ {
rwlock_t *rwl = (rwlock_t *)arg; rwlock_t* rwl = (rwlock_t*) arg;
rwl->w_wait--; rwl->w_wait--;
pthread_mutex_unlock (&rwl->mutex); pthread_mutex_unlock(&rwl->mutex);
} }
/* /*
* Lock a read-write lock for write access. * Lock a read-write lock for write access.
*/ */
int rwl_writelock (rwlock_t *rwl) int
rwl_writelock(rwlock_t* rwl)
{ {
int status; int status;
if (rwl->valid != RWLOCK_VALID) if (rwl->valid != RWLOCK_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&rwl->mutex); status = pthread_mutex_lock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
if (rwl->w_active || rwl->r_active > 0) { if (rwl->w_active || rwl->r_active > 0) {
rwl->w_wait++; rwl->w_wait++;
pthread_cleanup_push (rwl_writecleanup, (void*)rwl); pthread_cleanup_push(rwl_writecleanup, (void*) rwl);
while (rwl->w_active || rwl->r_active > 0) { while (rwl->w_active || rwl->r_active > 0) {
status = pthread_cond_wait (&rwl->write, &rwl->mutex); status = pthread_cond_wait(&rwl->write, &rwl->mutex);
if (status != 0) if (status != 0)
break; break;
} }
pthread_cleanup_pop (0); pthread_cleanup_pop(0);
rwl->w_wait--; rwl->w_wait--;
} }
if (status == 0) if (status == 0)
rwl->w_active = 1; rwl->w_active = 1;
pthread_mutex_unlock (&rwl->mutex); pthread_mutex_unlock(&rwl->mutex);
return status; return status;
} }
@@ -228,49 +236,52 @@ int rwl_writelock (rwlock_t *rwl)
* Attempt to lock a read-write lock for write access. Don't * Attempt to lock a read-write lock for write access. Don't
* block if unavailable. * block if unavailable.
*/ */
int rwl_writetrylock (rwlock_t *rwl) int
rwl_writetrylock(rwlock_t* rwl)
{ {
int status, status2; int status, status2;
if (rwl->valid != RWLOCK_VALID) if (rwl->valid != RWLOCK_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&rwl->mutex); status = pthread_mutex_lock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
if (rwl->w_active || rwl->r_active > 0) if (rwl->w_active || rwl->r_active > 0)
status = EBUSY; status = EBUSY;
else else
rwl->w_active = 1; rwl->w_active = 1;
status2 = pthread_mutex_unlock (&rwl->mutex); status2 = pthread_mutex_unlock(&rwl->mutex);
return (status != 0 ? status : status2); return (status != 0 ? status : status2);
} }
/* /*
* Unlock a read-write lock from write access. * Unlock a read-write lock from write access.
*/ */
int rwl_writeunlock (rwlock_t *rwl) int
rwl_writeunlock(rwlock_t* rwl)
{ {
int status; int status;
if (rwl->valid != RWLOCK_VALID) if (rwl->valid != RWLOCK_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&rwl->mutex); status = pthread_mutex_lock(&rwl->mutex);
if (status != 0) if (status != 0)
return status; return status;
rwl->w_active = 0; rwl->w_active = 0;
if (rwl->r_wait > 0) { if (rwl->r_wait > 0) {
status = pthread_cond_broadcast (&rwl->read); status = pthread_cond_broadcast(&rwl->read);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&rwl->mutex); pthread_mutex_unlock(&rwl->mutex);
return status;
}
} else if (rwl->w_wait > 0) {
status = pthread_cond_signal (&rwl->write);
if (status != 0) {
pthread_mutex_unlock (&rwl->mutex);
return status; return status;
} }
} }
status = pthread_mutex_unlock (&rwl->mutex); else if (rwl->w_wait > 0) {
status = pthread_cond_signal(&rwl->write);
if (status != 0) {
pthread_mutex_unlock(&rwl->mutex);
return status;
}
}
status = pthread_mutex_unlock(&rwl->mutex);
return status; return status;
} }

View File

@@ -33,17 +33,19 @@ typedef struct rwlock_tag {
* Support static initialization of barriers * Support static initialization of barriers
*/ */
#define RWL_INITIALIZER \ #define RWL_INITIALIZER \
{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, \ { \
PTHREAD_COND_INITIALIZER, RWLOCK_VALID, 0, 0, 0, 0} PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, \
PTHREAD_COND_INITIALIZER, RWLOCK_VALID, 0, 0, 0, 0 \
}
/* /*
* Define read-write lock functions * Define read-write lock functions
*/ */
extern int rwl_init (rwlock_t *rwlock); extern int rwl_init(rwlock_t* rwlock);
extern int rwl_destroy (rwlock_t *rwlock); extern int rwl_destroy(rwlock_t* rwlock);
extern int rwl_readlock (rwlock_t *rwlock); extern int rwl_readlock(rwlock_t* rwlock);
extern int rwl_readtrylock (rwlock_t *rwlock); extern int rwl_readtrylock(rwlock_t* rwlock);
extern int rwl_readunlock (rwlock_t *rwlock); extern int rwl_readunlock(rwlock_t* rwlock);
extern int rwl_writelock (rwlock_t *rwlock); extern int rwl_writelock(rwlock_t* rwlock);
extern int rwl_writetrylock (rwlock_t *rwlock); extern int rwl_writetrylock(rwlock_t* rwlock);
extern int rwl_writeunlock (rwlock_t *rwlock); extern int rwl_writeunlock(rwlock_t* rwlock);

View File

@@ -8,8 +8,8 @@
* to allow interleaved thread execution, since threads are not * to allow interleaved thread execution, since threads are not
* timesliced. * timesliced.
*/ */
#include "rwlock.h"
#include "errors.h" #include "errors.h"
#include "rwlock.h"
#define THREADS 5 #define THREADS 5
#define DATASIZE 15 #define DATASIZE 15
@@ -41,9 +41,10 @@ data_t data[DATASIZE];
/* /*
* Thread start routine that uses read-write locks * Thread start routine that uses read-write locks
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
thread_t *self = (thread_t*)arg; thread_t* self = (thread_t*) arg;
int repeats = 0; int repeats = 0;
int iteration; int iteration;
int element = 0; int element = 0;
@@ -56,30 +57,31 @@ void *thread_routine (void *arg)
* lock). * lock).
*/ */
if ((iteration % self->interval) == 0) { if ((iteration % self->interval) == 0) {
status = rwl_writelock (&data[element].lock); status = rwl_writelock(&data[element].lock);
if (status != 0) if (status != 0)
err_abort (status, "Write lock"); err_abort(status, "Write lock");
data[element].data = self->thread_num; data[element].data = self->thread_num;
data[element].updates++; data[element].updates++;
self->updates++; self->updates++;
status = rwl_writeunlock (&data[element].lock); status = rwl_writeunlock(&data[element].lock);
if (status != 0) if (status != 0)
err_abort (status, "Write unlock"); err_abort(status, "Write unlock");
} else { }
else {
/* /*
* Look at the current data element to see whether * Look at the current data element to see whether
* the current thread last updated it. Count the * the current thread last updated it. Count the
* times, to report later. * times, to report later.
*/ */
status = rwl_readlock (&data[element].lock); status = rwl_readlock(&data[element].lock);
if (status != 0) if (status != 0)
err_abort (status, "Read lock"); err_abort(status, "Read lock");
self->reads++; self->reads++;
if (data[element].data == self->thread_num) if (data[element].data == self->thread_num)
repeats++; repeats++;
status = rwl_readunlock (&data[element].lock); status = rwl_readunlock(&data[element].lock);
if (status != 0) if (status != 0)
err_abort (status, "Read unlock"); err_abort(status, "Read unlock");
} }
element++; element++;
if (element >= DATASIZE) if (element >= DATASIZE)
@@ -87,13 +89,14 @@ void *thread_routine (void *arg)
} }
if (repeats > 0) if (repeats > 0)
printf ( printf("Thread %d found unchanged elements %d times\n",
"Thread %d found unchanged elements %d times\n", self->thread_num,
self->thread_num, repeats); repeats);
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int count; int count;
int data_count; int data_count;
@@ -108,8 +111,8 @@ int main (int argc, char *argv[])
* that our threads can run concurrently, we need to * that our threads can run concurrently, we need to
* increase the concurrency level to THREADS. * increase the concurrency level to THREADS.
*/ */
DPRINTF (("Setting concurrency level to %d\n", THREADS)); DPRINTF(("Setting concurrency level to %d\n", THREADS));
thr_setconcurrency (THREADS); thr_setconcurrency(THREADS);
#endif #endif
/* /*
@@ -118,9 +121,9 @@ int main (int argc, char *argv[])
for (data_count = 0; data_count < DATASIZE; data_count++) { for (data_count = 0; data_count < DATASIZE; data_count++) {
data[data_count].data = 0; data[data_count].data = 0;
data[data_count].updates = 0; data[data_count].updates = 0;
status = rwl_init (&data[data_count].lock); status = rwl_init(&data[data_count].lock);
if (status != 0) if (status != 0)
err_abort (status, "Init rw lock"); err_abort(status, "Init rw lock");
} }
/* /*
@@ -130,11 +133,13 @@ int main (int argc, char *argv[])
threads[count].thread_num = count; threads[count].thread_num = count;
threads[count].updates = 0; threads[count].updates = 0;
threads[count].reads = 0; threads[count].reads = 0;
threads[count].interval = rand_r (&seed) % 71; threads[count].interval = rand_r(&seed) % 71;
status = pthread_create (&threads[count].thread_id, status = pthread_create(&threads[count].thread_id,
NULL, thread_routine, (void*)&threads[count]); NULL,
thread_routine,
(void*) &threads[count]);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
/* /*
@@ -142,13 +147,15 @@ int main (int argc, char *argv[])
* statistics. * statistics.
*/ */
for (count = 0; count < THREADS; count++) { for (count = 0; count < THREADS; count++) {
status = pthread_join (threads[count].thread_id, NULL); status = pthread_join(threads[count].thread_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
thread_updates += threads[count].updates; thread_updates += threads[count].updates;
printf ("%02d: interval %d, updates %d, reads %d\n", printf("%02d: interval %d, updates %d, reads %d\n",
count, threads[count].interval, count,
threads[count].updates, threads[count].reads); threads[count].interval,
threads[count].updates,
threads[count].reads);
} }
/* /*
@@ -156,12 +163,13 @@ int main (int argc, char *argv[])
*/ */
for (data_count = 0; data_count < DATASIZE; data_count++) { for (data_count = 0; data_count < DATASIZE; data_count++) {
data_updates += data[data_count].updates; data_updates += data[data_count].updates;
printf ("data %02d: value %d, %d updates\n", printf("data %02d: value %d, %d updates\n",
data_count, data[data_count].data, data[data_count].updates); data_count,
rwl_destroy (&data[data_count].lock); data[data_count].data,
data[data_count].updates);
rwl_destroy(&data[data_count].lock);
} }
printf ("%d thread updates, %d data updates\n", printf("%d thread updates, %d data updates\n", thread_updates, data_updates);
thread_updates, data_updates);
return 0; return 0;
} }

View File

@@ -8,8 +8,8 @@
* timesliced. * timesliced.
*/ */
#include <pthread.h> #include <pthread.h>
#include "rwlock.h"
#include "errors.h" #include "errors.h"
#include "rwlock.h"
#define THREADS 5 #define THREADS 5
#define ITERATIONS 1000 #define ITERATIONS 1000
@@ -42,9 +42,10 @@ data_t data[DATASIZE];
/* /*
* Thread start routine that uses read-write locks * Thread start routine that uses read-write locks
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
thread_t *self = (thread_t*)arg; thread_t* self = (thread_t*) arg;
int iteration; int iteration;
int element; int element;
int status; int status;
@@ -53,28 +54,33 @@ void *thread_routine (void *arg)
for (iteration = 0; iteration < ITERATIONS; iteration++) { for (iteration = 0; iteration < ITERATIONS; iteration++) {
if ((iteration % self->interval) == 0) { if ((iteration % self->interval) == 0) {
status = rwl_writetrylock (&data[element].lock); status = rwl_writetrylock(&data[element].lock);
if (status == EBUSY) if (status == EBUSY)
self->w_collisions++; self->w_collisions++;
else if (status == 0) { else if (status == 0) {
data[element].data++; data[element].data++;
data[element].updates++; data[element].updates++;
self->updates++; self->updates++;
rwl_writeunlock (&data[element].lock); rwl_writeunlock(&data[element].lock);
} else }
err_abort (status, "Try write lock"); else
} else { err_abort(status, "Try write lock");
status = rwl_readtrylock (&data[element].lock); }
else {
status = rwl_readtrylock(&data[element].lock);
if (status == EBUSY) if (status == EBUSY)
self->r_collisions++; self->r_collisions++;
else if (status != 0) { else if (status != 0) {
err_abort (status, "Try read lock"); err_abort(status, "Try read lock");
} else { }
else {
if (data[element].data != data[element].updates) if (data[element].data != data[element].updates)
printf ("%d: data[%d] %d != %d\n", printf("%d: data[%d] %d != %d\n",
self->thread_num, element, self->thread_num,
data[element].data, data[element].updates); element,
rwl_readunlock (&data[element].lock); data[element].data,
data[element].updates);
rwl_readunlock(&data[element].lock);
} }
} }
@@ -85,7 +91,8 @@ void *thread_routine (void *arg)
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
int count, data_count; int count, data_count;
unsigned int seed = 1; unsigned int seed = 1;
@@ -98,8 +105,8 @@ int main (int argc, char *argv[])
* that our threads can run concurrently, we need to * that our threads can run concurrently, we need to
* increase the concurrency level to THREADS. * increase the concurrency level to THREADS.
*/ */
DPRINTF (("Setting concurrency level to %d\n", THREADS)); DPRINTF(("Setting concurrency level to %d\n", THREADS));
thr_setconcurrency (THREADS); thr_setconcurrency(THREADS);
#endif #endif
/* /*
@@ -108,7 +115,7 @@ int main (int argc, char *argv[])
for (data_count = 0; data_count < DATASIZE; data_count++) { for (data_count = 0; data_count < DATASIZE; data_count++) {
data[data_count].data = 0; data[data_count].data = 0;
data[data_count].updates = 0; data[data_count].updates = 0;
rwl_init (&data[data_count].lock); rwl_init(&data[data_count].lock);
} }
/* /*
@@ -119,11 +126,13 @@ int main (int argc, char *argv[])
threads[count].r_collisions = 0; threads[count].r_collisions = 0;
threads[count].w_collisions = 0; threads[count].w_collisions = 0;
threads[count].updates = 0; threads[count].updates = 0;
threads[count].interval = rand_r (&seed) % ITERATIONS; threads[count].interval = rand_r(&seed) % ITERATIONS;
status = pthread_create (&threads[count].thread_id, status = pthread_create(&threads[count].thread_id,
NULL, thread_routine, (void*)&threads[count]); NULL,
thread_routine,
(void*) &threads[count]);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
} }
/* /*
@@ -131,15 +140,18 @@ int main (int argc, char *argv[])
* statistics. * statistics.
*/ */
for (count = 0; count < THREADS; count++) { for (count = 0; count < THREADS; count++) {
status = pthread_join (threads[count].thread_id, NULL); status = pthread_join(threads[count].thread_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
thread_updates += threads[count].updates; thread_updates += threads[count].updates;
printf ("%02d: interval %d, updates %d, " printf(
"%02d: interval %d, updates %d, "
"r_collisions %d, w_collisions %d\n", "r_collisions %d, w_collisions %d\n",
count, threads[count].interval, count,
threads[count].interval,
threads[count].updates, threads[count].updates,
threads[count].r_collisions, threads[count].w_collisions); threads[count].r_collisions,
threads[count].w_collisions);
} }
/* /*
@@ -147,9 +159,11 @@ int main (int argc, char *argv[])
*/ */
for (data_count = 0; data_count < DATASIZE; data_count++) { for (data_count = 0; data_count < DATASIZE; data_count++) {
data_updates += data[data_count].updates; data_updates += data[data_count].updates;
printf ("data %02d: value %d, %d updates\n", printf("data %02d: value %d, %d updates\n",
data_count, data[data_count].data, data[data_count].updates); data_count,
rwl_destroy (&data[data_count].lock); data[data_count].data,
data[data_count].updates);
rwl_destroy(&data[data_count].lock);
} }
return 0; return 0;

View File

@@ -20,20 +20,21 @@
* processing threads will begin to shut down. (They will be * processing threads will begin to shut down. (They will be
* restarted when work appears.) * restarted when work appears.)
*/ */
#include "workq.h"
#include <pthread.h> #include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include "errors.h" #include "errors.h"
#include "workq.h"
/* /*
* Thread start routine to serve the work queue. * Thread start routine to serve the work queue.
*/ */
static void *workq_server (void *arg) static void*
workq_server(void* arg)
{ {
struct timespec timeout; struct timespec timeout;
workq_t *wq = (workq_t *)arg; workq_t* wq = (workq_t*) arg;
workq_ele_t *we; workq_ele_t* we;
int status, timedout; int status, timedout;
/* /*
@@ -43,15 +44,15 @@ static void *workq_server (void *arg)
* server threads to terminate before destroying a work * server threads to terminate before destroying a work
* queue. * queue.
*/ */
DPRINTF (("A worker is starting\n")); DPRINTF(("A worker is starting\n"));
status = pthread_mutex_lock (&wq->mutex); status = pthread_mutex_lock(&wq->mutex);
if (status != 0) if (status != 0)
return NULL; return NULL;
while (1) { while (1) {
timedout = 0; timedout = 0;
DPRINTF (("Worker waiting for work\n")); DPRINTF(("Worker waiting for work\n"));
clock_gettime (CLOCK_REALTIME, &timeout); clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 2; timeout.tv_sec += 2;
while (wq->first == NULL && !wq->quit) { while (wq->first == NULL && !wq->quit) {
@@ -59,13 +60,13 @@ static void *workq_server (void *arg)
* Server threads time out after spending 2 seconds * Server threads time out after spending 2 seconds
* waiting for new work, and exit. * waiting for new work, and exit.
*/ */
status = pthread_cond_timedwait ( status = pthread_cond_timedwait(&wq->cv, &wq->mutex, &timeout);
&wq->cv, &wq->mutex, &timeout);
if (status == ETIMEDOUT) { if (status == ETIMEDOUT) {
DPRINTF (("Worker wait timed out\n")); DPRINTF(("Worker wait timed out\n"));
timedout = 1; timedout = 1;
break; break;
} else if (status != 0) { }
else if (status != 0) {
/* /*
* This shouldn't happen, so the work queue * This shouldn't happen, so the work queue
* package should fail. Because the work queue * package should fail. Because the work queue
@@ -80,28 +81,26 @@ static void *workq_server (void *arg)
* queued. That could be fixed by creating a new * queued. That could be fixed by creating a new
* server here. * server here.
*/ */
DPRINTF (( DPRINTF(("Worker wait failed, %d (%s)\n", status, strerror(status)));
"Worker wait failed, %d (%s)\n",
status, strerror (status)));
wq->counter--; wq->counter--;
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
return NULL; return NULL;
} }
} }
DPRINTF (("Work queue: %#lx, quit: %d\n", wq->first, wq->quit)); DPRINTF(("Work queue: %#lx, quit: %d\n", wq->first, wq->quit));
we = wq->first; we = wq->first;
if (we != NULL) { if (we != NULL) {
wq->first = we->next; wq->first = we->next;
if (wq->last == we) if (wq->last == we)
wq->last = NULL; wq->last = NULL;
status = pthread_mutex_unlock (&wq->mutex); status = pthread_mutex_unlock(&wq->mutex);
if (status != 0) if (status != 0)
return NULL; return NULL;
DPRINTF (("Worker calling engine\n")); DPRINTF(("Worker calling engine\n"));
wq->engine (we->data); wq->engine(we->data);
free (we); free(we);
status = pthread_mutex_lock (&wq->mutex); status = pthread_mutex_lock(&wq->mutex);
if (status != 0) if (status != 0)
return NULL; return NULL;
} }
@@ -111,7 +110,7 @@ static void *workq_server (void *arg)
* have been asked to quit, then shut down. * have been asked to quit, then shut down.
*/ */
if (wq->first == NULL && wq->quit) { if (wq->first == NULL && wq->quit) {
DPRINTF (("Worker shutting down\n")); DPRINTF(("Worker shutting down\n"));
wq->counter--; wq->counter--;
/* /*
@@ -125,8 +124,8 @@ static void *workq_server (void *arg)
* signaled exactly once! * signaled exactly once!
*/ */
if (wq->counter == 0) if (wq->counter == 0)
pthread_cond_broadcast (&wq->cv); pthread_cond_broadcast(&wq->cv);
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
return NULL; return NULL;
} }
@@ -135,42 +134,42 @@ static void *workq_server (void *arg)
* we're allowed, then terminate this server thread. * we're allowed, then terminate this server thread.
*/ */
if (wq->first == NULL && timedout) { if (wq->first == NULL && timedout) {
DPRINTF (("engine terminating due to timeout.\n")); DPRINTF(("engine terminating due to timeout.\n"));
wq->counter--; wq->counter--;
break; break;
} }
} }
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
DPRINTF (("Worker exiting\n")); DPRINTF(("Worker exiting\n"));
return NULL; return NULL;
} }
/* /*
* Initialize a work queue. * Initialize a work queue.
*/ */
int workq_init (workq_t *wq, int threads, void (*engine)(void *arg)) int
workq_init(workq_t* wq, int threads, void (*engine)(void* arg))
{ {
int status; int status;
status = pthread_attr_init (&wq->attr); status = pthread_attr_init(&wq->attr);
if (status != 0) if (status != 0)
return status; return status;
status = pthread_attr_setdetachstate ( status = pthread_attr_setdetachstate(&wq->attr, PTHREAD_CREATE_DETACHED);
&wq->attr, PTHREAD_CREATE_DETACHED);
if (status != 0) { if (status != 0) {
pthread_attr_destroy (&wq->attr); pthread_attr_destroy(&wq->attr);
return status; return status;
} }
status = pthread_mutex_init (&wq->mutex, NULL); status = pthread_mutex_init(&wq->mutex, NULL);
if (status != 0) { if (status != 0) {
pthread_attr_destroy (&wq->attr); pthread_attr_destroy(&wq->attr);
return status; return status;
} }
status = pthread_cond_init (&wq->cv, NULL); status = pthread_cond_init(&wq->cv, NULL);
if (status != 0) { if (status != 0) {
pthread_mutex_destroy (&wq->mutex); pthread_mutex_destroy(&wq->mutex);
pthread_attr_destroy (&wq->attr); pthread_attr_destroy(&wq->attr);
return status; return status;
} }
wq->quit = 0; /* not time to quit */ wq->quit = 0; /* not time to quit */
@@ -186,13 +185,14 @@ int workq_init (workq_t *wq, int threads, void (*engine)(void *arg))
/* /*
* Destroy a work queue. * Destroy a work queue.
*/ */
int workq_destroy (workq_t *wq) int
workq_destroy(workq_t* wq)
{ {
int status, status1, status2; int status, status1, status2;
if (wq->valid != WORKQ_VALID) if (wq->valid != WORKQ_VALID)
return EINVAL; return EINVAL;
status = pthread_mutex_lock (&wq->mutex); status = pthread_mutex_lock(&wq->mutex);
if (status != 0) if (status != 0)
return status; return status;
wq->valid = 0; /* prevent any other operations */ wq->valid = 0; /* prevent any other operations */
@@ -210,9 +210,9 @@ int workq_destroy (workq_t *wq)
wq->quit = 1; wq->quit = 1;
/* if any threads are idling, wake them. */ /* if any threads are idling, wake them. */
if (wq->idle > 0) { if (wq->idle > 0) {
status = pthread_cond_broadcast (&wq->cv); status = pthread_cond_broadcast(&wq->cv);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
return status; return status;
} }
} }
@@ -227,28 +227,29 @@ int workq_destroy (workq_t *wq)
* waited and signalled exactly once! * waited and signalled exactly once!
*/ */
while (wq->counter > 0) { while (wq->counter > 0) {
status = pthread_cond_wait (&wq->cv, &wq->mutex); status = pthread_cond_wait(&wq->cv, &wq->mutex);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
return status; return status;
} }
} }
} }
status = pthread_mutex_unlock (&wq->mutex); status = pthread_mutex_unlock(&wq->mutex);
if (status != 0) if (status != 0)
return status; return status;
status = pthread_mutex_destroy (&wq->mutex); status = pthread_mutex_destroy(&wq->mutex);
status1 = pthread_cond_destroy (&wq->cv); status1 = pthread_cond_destroy(&wq->cv);
status2 = pthread_attr_destroy (&wq->attr); status2 = pthread_attr_destroy(&wq->attr);
return (status ? status : (status1 ? status1 : status2)); return (status ? status : (status1 ? status1 : status2));
} }
/* /*
* Add an item to a work queue. * Add an item to a work queue.
*/ */
int workq_add (workq_t *wq, void *element) int
workq_add(workq_t* wq, void* element)
{ {
workq_ele_t *item; workq_ele_t* item;
pthread_t id; pthread_t id;
int status; int status;
@@ -258,14 +259,14 @@ int workq_add (workq_t *wq, void *element)
/* /*
* Create and initialize a request structure. * Create and initialize a request structure.
*/ */
item = (workq_ele_t *)malloc (sizeof (workq_ele_t)); item = (workq_ele_t*) malloc(sizeof(workq_ele_t));
if (item == NULL) if (item == NULL)
return ENOMEM; return ENOMEM;
item->data = element; item->data = element;
item->next = NULL; item->next = NULL;
status = pthread_mutex_lock (&wq->mutex); status = pthread_mutex_lock(&wq->mutex);
if (status != 0) { if (status != 0) {
free (item); free(item);
return status; return status;
} }
@@ -283,25 +284,25 @@ int workq_add (workq_t *wq, void *element)
* if any threads are idling, wake one. * if any threads are idling, wake one.
*/ */
if (wq->idle > 0) { if (wq->idle > 0) {
status = pthread_cond_signal (&wq->cv); status = pthread_cond_signal(&wq->cv);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
return status; return status;
} }
} else if (wq->counter < wq->parallelism) { }
else if (wq->counter < wq->parallelism) {
/* /*
* If there were no idling threads, and we're allowed to * If there were no idling threads, and we're allowed to
* create a new thread, do so. * create a new thread, do so.
*/ */
DPRINTF (("Creating new worker\n")); DPRINTF(("Creating new worker\n"));
status = pthread_create ( status = pthread_create(&id, &wq->attr, workq_server, (void*) wq);
&id, &wq->attr, workq_server, (void*)wq);
if (status != 0) { if (status != 0) {
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
return status; return status;
} }
wq->counter++; wq->counter++;
} }
pthread_mutex_unlock (&wq->mutex); pthread_mutex_unlock(&wq->mutex);
return 0; return 0;
} }

View File

@@ -26,8 +26,8 @@
* Structure to keep track of work queue requests. * Structure to keep track of work queue requests.
*/ */
typedef struct workq_ele_tag { typedef struct workq_ele_tag {
struct workq_ele_tag *next; struct workq_ele_tag* next;
void *data; void* data;
} workq_ele_t; } workq_ele_t;
/* /*
@@ -43,7 +43,7 @@ typedef struct workq_tag {
int parallelism; /* number of threads required */ int parallelism; /* number of threads required */
int counter; /* current number of threads */ int counter; /* current number of threads */
int idle; /* number of idle threads */ int idle; /* number of idle threads */
void (*engine)(void *arg); /* user engine */ void (*engine)(void* arg); /* user engine */
} workq_t; } workq_t;
#define WORKQ_VALID 0xdec1992 #define WORKQ_VALID 0xdec1992
@@ -51,9 +51,8 @@ typedef struct workq_tag {
/* /*
* Define work queue functions * Define work queue functions
*/ */
extern int workq_init ( extern int workq_init(workq_t* wq,
workq_t *wq,
int threads, /* maximum threads */ int threads, /* maximum threads */
void (*engine)(void *)); /* engine routine */ void (*engine)(void*)); /* engine routine */
extern int workq_destroy (workq_t *wq); extern int workq_destroy(workq_t* wq);
extern int workq_add (workq_t *wq, void *data); extern int workq_add(workq_t* wq, void* data);

View File

@@ -4,11 +4,11 @@
* Demonstrate a use of work queues. * Demonstrate a use of work queues.
*/ */
#include <pthread.h> #include <pthread.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <time.h> #include <time.h>
#include "workq.h"
#include "errors.h" #include "errors.h"
#include "workq.h"
#define ITERATIONS 25 #define ITERATIONS 25
@@ -18,113 +18,112 @@ typedef struct power_tag {
} power_t; } power_t;
typedef struct engine_tag { typedef struct engine_tag {
struct engine_tag *link; struct engine_tag* link;
pthread_t thread_id; pthread_t thread_id;
int calls; int calls;
} engine_t; } engine_t;
pthread_key_t engine_key; /* Keep track of active engines */ pthread_key_t engine_key; /* Keep track of active engines */
pthread_mutex_t engine_list_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t engine_list_mutex = PTHREAD_MUTEX_INITIALIZER;
engine_t *engine_list_head = NULL; engine_t* engine_list_head = NULL;
workq_t workq; workq_t workq;
/* /*
* Thread-specific data destructor routine for engine_key * Thread-specific data destructor routine for engine_key
*/ */
void destructor (void *value_ptr) void
destructor(void* value_ptr)
{ {
engine_t *engine = (engine_t*)value_ptr; engine_t* engine = (engine_t*) value_ptr;
pthread_mutex_lock (&engine_list_mutex); pthread_mutex_lock(&engine_list_mutex);
engine->link = engine_list_head; engine->link = engine_list_head;
engine_list_head = engine; engine_list_head = engine;
pthread_mutex_unlock (&engine_list_mutex); pthread_mutex_unlock(&engine_list_mutex);
} }
/* /*
* This is the routine called by the work queue servers to * This is the routine called by the work queue servers to
* perform operations in parallel. * perform operations in parallel.
*/ */
void engine_routine (void *arg) void
engine_routine(void* arg)
{ {
engine_t *engine; engine_t* engine;
power_t *power = (power_t*)arg; power_t* power = (power_t*) arg;
int result, count; int result, count;
int status; int status;
engine = pthread_getspecific (engine_key); engine = pthread_getspecific(engine_key);
if (engine == NULL) { if (engine == NULL) {
engine = (engine_t*)malloc (sizeof (engine_t)); engine = (engine_t*) malloc(sizeof(engine_t));
status = pthread_setspecific ( status = pthread_setspecific(engine_key, (void*) engine);
engine_key, (void*)engine);
if (status != 0) if (status != 0)
err_abort (status, "Set tsd"); err_abort(status, "Set tsd");
engine->thread_id = pthread_self (); engine->thread_id = pthread_self();
engine->calls = 1; engine->calls = 1;
} else }
else
engine->calls++; engine->calls++;
result = 1; result = 1;
printf ( printf("Engine: computing %d^%d\n", power->value, power->power);
"Engine: computing %d^%d\n", for (count = 1; count <= power->power; count++) result *= power->value;
power->value, power->power); free(arg);
for (count = 1; count <= power->power; count++)
result *= power->value;
free (arg);
} }
/* /*
* Thread start routine that issues work queue requests. * Thread start routine that issues work queue requests.
*/ */
void *thread_routine (void *arg) void*
thread_routine(void* arg)
{ {
power_t *element; power_t* element;
int count; int count;
unsigned int seed = (unsigned int)time (NULL); unsigned int seed = (unsigned int) time(NULL);
int status; int status;
/* /*
* Loop, making requests. * Loop, making requests.
*/ */
for (count = 0; count < ITERATIONS; count++) { for (count = 0; count < ITERATIONS; count++) {
element = (power_t*)malloc (sizeof (power_t)); element = (power_t*) malloc(sizeof(power_t));
if (element == NULL) if (element == NULL)
errno_abort ("Allocate element"); errno_abort("Allocate element");
element->value = rand_r (&seed) % 20; element->value = rand_r(&seed) % 20;
element->power = rand_r (&seed) % 7; element->power = rand_r(&seed) % 7;
DPRINTF (( DPRINTF(("Request: %d^%d\n", element->value, element->power));
"Request: %d^%d\n", status = workq_add(&workq, (void*) element);
element->value, element->power));
status = workq_add (&workq, (void*)element);
if (status != 0) if (status != 0)
err_abort (status, "Add to work queue"); err_abort(status, "Add to work queue");
sleep (rand_r (&seed) % 5); sleep(rand_r(&seed) % 5);
} }
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t thread_id; pthread_t thread_id;
engine_t *engine; engine_t* engine;
int count = 0, calls = 0; int count = 0, calls = 0;
int status; int status;
status = pthread_key_create (&engine_key, destructor); status = pthread_key_create(&engine_key, destructor);
if (status != 0) if (status != 0)
err_abort (status, "Create key"); err_abort(status, "Create key");
status = workq_init (&workq, 4, engine_routine); status = workq_init(&workq, 4, engine_routine);
if (status != 0) if (status != 0)
err_abort (status, "Init work queue"); err_abort(status, "Init work queue");
status = pthread_create (&thread_id, NULL, thread_routine, NULL); status = pthread_create(&thread_id, NULL, thread_routine, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
(void)thread_routine (NULL); (void) thread_routine(NULL);
status = pthread_join (thread_id, NULL); status = pthread_join(thread_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
status = workq_destroy (&workq); status = workq_destroy(&workq);
if (status != 0) if (status != 0)
err_abort (status, "Destroy work queue"); err_abort(status, "Destroy work queue");
/* /*
* By now, all of the engine_t structures have been placed * By now, all of the engine_t structures have been placed
@@ -135,10 +134,9 @@ int main (int argc, char *argv[])
while (engine != NULL) { while (engine != NULL) {
count++; count++;
calls += engine->calls; calls += engine->calls;
printf ("engine %d: %d calls\n", count, engine->calls); printf("engine %d: %d calls\n", count, engine->calls);
engine = engine->link; engine = engine->link;
} }
printf ("%d engine threads processed %d calls\n", printf("%d engine threads processed %d calls\n", count, calls);
count, calls);
return 0; return 0;
} }

View File

@@ -11,18 +11,20 @@
#include <pthread.h> #include <pthread.h>
#include "errors.h" #include "errors.h"
void *printer_thread (void *arg) void*
printer_thread(void* arg)
{ {
char *string = *(char**)arg; char* string = *(char**) arg;
printf ("%s\n", string); printf("%s\n", string);
return NULL; return NULL;
} }
int main (int argc, char *argv[]) int
main(int argc, char* argv[])
{ {
pthread_t printer_id; pthread_t printer_id;
char *string_ptr; char* string_ptr;
int i, status; int i, status;
#ifdef sun #ifdef sun
@@ -31,14 +33,14 @@ int main (int argc, char *argv[])
* that our two threads can run concurrently, we need to * that our two threads can run concurrently, we need to
* increase the concurrency level to 2. * increase the concurrency level to 2.
*/ */
DPRINTF (("Setting concurrency level to 2\n")); DPRINTF(("Setting concurrency level to 2\n"));
thr_setconcurrency (2); thr_setconcurrency(2);
#endif #endif
string_ptr = "Before value"; string_ptr = "Before value";
status = pthread_create ( status =
&printer_id, NULL, printer_thread, (void*)&string_ptr); pthread_create(&printer_id, NULL, printer_thread, (void*) &string_ptr);
if (status != 0) if (status != 0)
err_abort (status, "Create thread"); err_abort(status, "Create thread");
/* /*
* Give the thread a chance to get started if it's going to run * Give the thread a chance to get started if it's going to run
@@ -46,11 +48,12 @@ int main (int argc, char *argv[])
* to be timesliced. (This is a tricky balance, and the loop may * to be timesliced. (This is a tricky balance, and the loop may
* need to be adjusted on your system before you can see the bug.) * need to be adjusted on your system before you can see the bug.)
*/ */
for (i = 0; i < 10000000; i++); for (i = 0; i < 10000000; i++)
;
string_ptr = "After value"; string_ptr = "After value";
status = pthread_join (printer_id, NULL); status = pthread_join(printer_id, NULL);
if (status != 0) if (status != 0)
err_abort (status, "Join thread"); err_abort(status, "Join thread");
return 0; return 0;
} }