This is my first time dealing with threads.
When I run the program without the GetCurrentThreadId() function it executes without any issue.
When I add that line of code it still executes but crashes once it reaches the end. Why is this?
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
static int tix[500];
static int done = 0;
HANDLE ghSemaphore;
DWORD WINAPI ThreadFunction();
int main(void)
{
DWORD threadID1, threadID2, threadID3, threadID4;
HANDLE hThread1, hThread2, hThread3, hThread4;
for (int i = 0; i < 500; i++) //initialize array
{
tix[i] = 0;
}
ghSemaphore = CreateSemaphore(NULL, 1, 10, NULL);
hThread1 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID1);
hThread2 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID2);
hThread3 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID3);
hThread4 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID4);
//printf("The thread ID: %d.\n", threadID1);
//printf("The thread ID: %d.\n", threadID2);
//printf("The thread ID: %d.\n", threadID3);
//printf("The thread ID: %d.\n", threadID4);
if (done = 1)
{
CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(hThread3);
CloseHandle(hThread4);
}
for (int j = 0; j < 500; j++)
{
if (tix[j] = 0)
{
printf("not sold");
}
else if (tix[j] = 1)
{
printf("sold");
}
}
return 0;
}
DWORD WINAPI ThreadFunction()
{
WaitForSingleObject(ghSemaphore, 0);
printf("current thread running : %d\n", GetCurrentThreadId());
int i = 0;
if (done != 0) // if loop to test wether or not the array is full
{
while (tix[i] = 1) //traverse the array to find a open spot
{
i++;
}
tix[i] = 1;
}
if (i == 499) //if i is 499, set test variable to 1
{
done = 1;
return 0;
}
ReleaseSemaphore(ghSemaphore, 1, NULL);
}
Your thread function has incorrect signature. Thread takes one PVOID context argument:
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
Your threads could exit without releasing a semaphore. Also since you had initialized it with a value, that is greater than thread amount and never check WaitForSingleObject result, no synchronization is provided and multiple threads will modify a shared buffers in inconsistent manner. Even worse - nothing stops your program main thread exiting earlier, than ThreadFunction.
There is no return statement in the end of your thread function, so this is an undefined behavior. In fact it is a great wonder that your code even compiles. This entire approach to multithreading is incorrect and has to be remade from the scratch.
Related
I'm trying to solve the classic "single lane tunnel" semaphore/mutex problem.
This is the code I wrote but it doesn't work and I can't understand why.
In theory the cars coming from opposite direction should cross ONLY if the tunnel is already in use by cars going in the same direction otherwise they should wait, the output should be something like:
car1_leftToRight crossing
car2_leftToRight crossing
car1_leftToRight end crossing
car2_leftToRight end crossing (ALL cars leftToRight have crossed)
car1_rightToLeft start crossing
etc..
but my current output is the one that you can see in the image I attached.
I also created a global variable (globalCarsCrossing) to keep track on how many cars are currently crossing the bridge and as you can see it seems that cars from opposite directions are crossing at the same time!
Do you have some suggestion on what I'm doing wrong?
#define UNICODE
#define _UNICODE
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <WinBase.h>
#include <process.h> //include for function _beginthreadex
int globalCarsCrossing = 0;
typedef struct {
int numTraversingCar;
int crossingTime;
int arrivalTime; //0 - arrivalTime -> random number, how much time pass between cars arrival
HANDLE mutex;
LPHANDLE bridgeMutexPtr;
int direction;
} ThParams;
DWORD WINAPI thFunction(LPVOID thParamsPtr);
void crossBridge();
int _tmain(int argc, LPTSTR argv[])
{
int timeL2R, timeR2L, timeARRIVAL, nL2R, nR2L;
LPHANDLE thL2Rarray, thR2Larray;
ThParams paramsL2R, paramsR2L;
HANDLE bridgeMutex;
if (argc < 6)
{
_ftprintf(stderr, _T("missing parameters: <timeL2R> <timeR2L> <timeARRIVAL> <nL2R> <nR2L>\n"));
exit(EXIT_FAILURE);
}
timeL2R = _ttoi(argv[1]); //WINDOWS version of "atoi"
timeR2L = _ttoi(argv[2]);
timeARRIVAL = _ttoi(argv[3]);
nL2R = _ttoi(argv[4]);
nR2L = _ttoi(argv[5]);
//allocates all threads array
thL2Rarray = (LPHANDLE)malloc(nL2R * sizeof(HANDLE));
thR2Larray = (LPHANDLE)malloc(nR2L * sizeof(HANDLE));
//initialize all parameters
bridgeMutex = CreateMutex(NULL, FALSE, NULL);
//create structs for threads
paramsL2R.mutex = CreateMutex(NULL, FALSE, NULL);
paramsL2R.bridgeMutexPtr = &bridgeMutex;
paramsL2R.arrivalTime = timeARRIVAL;
paramsL2R.numTraversingCar = 0;
paramsL2R.crossingTime = timeL2R;
paramsL2R.direction = 0;
//paramsR2L.criticalSectionPtr = &criticalSectionR2L;
paramsR2L.mutex = CreateMutex(NULL, FALSE, NULL);
paramsR2L.bridgeMutexPtr = &bridgeMutex;
paramsR2L.arrivalTime = timeARRIVAL;
paramsR2L.numTraversingCar = 0;
paramsR2L.crossingTime = timeR2L;
paramsR2L.direction = 1;
//create L2R threads
for (int i = 0; i<nL2R; i++)
thL2Rarray[i] = CreateThread(NULL, 0, thFunction, ¶msL2R, 0, NULL);
//create R2L threads
for (int i = 0; i<nR2L; i++)
thR2Larray[i] = CreateThread(NULL, 0, thFunction, ¶msR2L, 0, NULL);
//wait for ALL threads to return
WaitForMultipleObjects(nL2R, thL2Rarray, TRUE, INFINITE);
WaitForMultipleObjects(nR2L, thR2Larray, TRUE, INFINITE);
_tprintf(_T("all threads are returned\n"));
//closa all thread handle
for (int i = 0; i<nL2R; i++)
CloseHandle(thL2Rarray[i]);
for (int i = 0; i<nR2L; i++)
CloseHandle(thR2Larray[i]);
////free and release everything
free(thL2Rarray);
free(thR2Larray);
CloseHandle(bridgeMutex);
CloseHandle(paramsR2L.mutex);
CloseHandle(paramsL2R.mutex);
return 0;
}
DWORD WINAPI thFunction(LPVOID thParamsPtr)
{
ThParams *paramsPtr = (ThParams *)thParamsPtr;
WaitForSingleObject(paramsPtr->mutex, INFINITE);
paramsPtr->numTraversingCar = paramsPtr->numTraversingCar + 1;
if (paramsPtr->numTraversingCar == 1)
WaitForSingleObject(*(paramsPtr->bridgeMutexPtr), INFINITE);
globalCarsCrossing++;
_tprintf(_T("%d crossing direction: %d, TOT_cars_from_this_direction: %d, GLOBAL_CARS_CROSSING: %d\n"), GetCurrentThreadId(), paramsPtr->direction, paramsPtr->numTraversingCar, globalCarsCrossing);
ReleaseMutex(paramsPtr->mutex);
crossBridge();
WaitForSingleObject(paramsPtr->mutex, INFINITE);
paramsPtr->numTraversingCar = paramsPtr->numTraversingCar - 1;
globalCarsCrossing--;
_tprintf(_T("%d end crossing direction: %d, TOT_cars_from_this_direction: %d, GLOBAL_CARS_CROSSING %d\n"), GetCurrentThreadId(), paramsPtr->direction, paramsPtr->numTraversingCar, globalCarsCrossing);
if (paramsPtr->numTraversingCar == 0) {
_tprintf(_T("RELEASED\n"));
ReleaseMutex(*(paramsPtr->bridgeMutexPtr));
}
ReleaseMutex(paramsPtr->mutex);
return 0;
}
The problem comes from your WaitForSingleObject call:
Return code: WAIT_ABANDONED 0x00000080L
The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread and the mutex state is set to nonsignaled.
If the mutex was protecting persistent state information, you should check it for consistency.
Thread 2944 got the mutex on tunnel, made its car cross and finish, without releasing the mutex.
When thread 3560 calls WaitForSingleObject, this function returns WAIT_ABANDONED
Your code cannot do what you want because a mutex took by a thread must be released by the same thread.
A semaphore is more appropriated to lock the tunnel.
Edit:
I first post I suggested using CriticalSection, but like Mutex, a CriticalSection must be acquired and release by the same thread.
Example implementation:
#define UNICODE
#define _UNICODE
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <WinBase.h>
#include <process.h> //include for function _beginthreadex
int globalCarsCrossing = 0;
typedef struct {
int numTraversingCar;
int crossingTime;
int arrivalTime; //0 - arrivalTime -> random number, how much time pass between cars arrival
HANDLE mutex;
HANDLE bridgeSem;
int direction;
} ThParams;
DWORD WINAPI thFunction(LPVOID thParamsPtr);
void crossBridge();
int _tmain(int argc, LPTSTR argv[])
{
int timeL2R, timeR2L, timeARRIVAL, nL2R, nR2L;
LPHANDLE thL2Rarray, thR2Larray;
ThParams paramsL2R, paramsR2L;
HANDLE bridgeSem;
if (argc < 6)
{
_ftprintf(stderr, _T("missing parameters: <timeL2R> <timeR2L> <timeARRIVAL> <nL2R> <nR2L>\n"));
exit(EXIT_FAILURE);
}
timeL2R = _ttoi(argv[1]); //WINDOWS version of "atoi"
timeR2L = _ttoi(argv[2]);
timeARRIVAL = _ttoi(argv[3]);
nL2R = _ttoi(argv[4]);
nR2L = _ttoi(argv[5]);
//allocates all threads array
thL2Rarray = (LPHANDLE)malloc(nL2R * sizeof(HANDLE));
thR2Larray = (LPHANDLE)malloc(nR2L * sizeof(HANDLE));
//initialize all parameters
bridgeSem = CreateSemaphore(NULL, 1, 1, NULL);
//create structs for threads
paramsL2R.mutex = CreateMutex(NULL, FALSE, NULL);
paramsL2R.bridgeSem = bridgeSem;
paramsL2R.arrivalTime = timeARRIVAL;
paramsL2R.numTraversingCar = 0;
paramsL2R.crossingTime = timeL2R;
paramsL2R.direction = 0;
//paramsR2L.criticalSectionPtr = &criticalSectionR2L;
paramsR2L.mutex = CreateMutex(NULL, FALSE, NULL);
paramsR2L.bridgeSem = bridgeSem;
paramsR2L.arrivalTime = timeARRIVAL;
paramsR2L.numTraversingCar = 0;
paramsR2L.crossingTime = timeR2L;
paramsR2L.direction = 1;
//create L2R threads
for (int i = 0; i<nL2R; i++)
thL2Rarray[i] = CreateThread(NULL, 0, thFunction, ¶msL2R, 0, NULL);
//create R2L threads
for (int i = 0; i<nR2L; i++)
thR2Larray[i] = CreateThread(NULL, 0, thFunction, ¶msR2L, 0, NULL);
//wait for ALL threads to return
WaitForMultipleObjects(nL2R, thL2Rarray, TRUE, INFINITE);
WaitForMultipleObjects(nR2L, thR2Larray, TRUE, INFINITE);
_tprintf(_T("all threads are returned\n"));
//closa all thread handle
for (int i = 0; i<nL2R; i++)
CloseHandle(thL2Rarray[i]);
for (int i = 0; i<nR2L; i++)
CloseHandle(thR2Larray[i]);
////free and release everything
free(thL2Rarray);
free(thR2Larray);
CloseHandle(bridgeSem);
CloseHandle(paramsR2L.mutex);
CloseHandle(paramsL2R.mutex);
return 0;
}
DWORD WINAPI thFunction(LPVOID thParamsPtr)
{
ThParams *paramsPtr = (ThParams *)thParamsPtr;
WaitForSingleObject(paramsPtr->mutex, INFINITE);
paramsPtr->numTraversingCar = paramsPtr->numTraversingCar + 1;
if (paramsPtr->numTraversingCar == 1)
WaitForSingleObject(paramsPtr->bridgeSem, INFINITE);
globalCarsCrossing++;
_tprintf(_T("%d crossing direction: %d, TOT_cars_from_this_direction: %d, GLOBAL_CARS_CROSSING: %d\n"), GetCurrentThreadId(), paramsPtr->direction, paramsPtr->numTraversingCar, globalCarsCrossing);
ReleaseMutex(paramsPtr->mutex);
crossBridge();
WaitForSingleObject(paramsPtr->mutex, INFINITE);
paramsPtr->numTraversingCar = paramsPtr->numTraversingCar - 1;
globalCarsCrossing--;
_tprintf(_T("%d end crossing direction: %d, TOT_cars_from_this_direction: %d, GLOBAL_CARS_CROSSING %d\n"), GetCurrentThreadId(), paramsPtr->direction, paramsPtr->numTraversingCar, globalCarsCrossing);
if (paramsPtr->numTraversingCar == 0) {
_tprintf(_T("RELEASED\n"));
ReleaseSemaphore(paramsPtr->bridgeSem, 1, NULL);
}
ReleaseMutex(paramsPtr->mutex);
return 0;
}
I met a strange problem while studying the Peterson Algorithm. When I finish my program, I was told that I should restrict that two particular threads (thread1 and thread2) to a single CPU core (I don't exactly know why I should do this, but my teacher told me that if I want to run two mutual exclusion processes with single resources without conflict, multi-core CPU may cause bug so I should restrict them to a single core) so I add the SetThreadAffinityMask() to do this.
But after I added this function, my code doesn't work, it was stuck into a infinite loop in thread1, not like the result before I add this function, which is work as well as I expected.
Here's my code
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
int nAccount1 = 0, nAccount2 = 0;
DWORD start, end;
int flag = 0;
int Process[2] = { 0 };
int Turn = 0;
DWORD WINAPI ThreadExecutive_1(LPVOID lpParameter) {
int nLoop = 0;
int nTemp1, nTemp2, nRandom;
int* pID = (int*)lpParameter;
//printf("Thread: %d Built successfully!\n", *pID);
do {
Process[0] = 1;
Turn = 1;
while (Process[1] == 1 && Turn == 1);
nTemp1 = nAccount1;
nTemp2 = nAccount2;
nRandom = rand();
nAccount1 = nTemp1 + nRandom;
nAccount2 = nTemp2 - nRandom;
Process[0] = 0;
nLoop++;
if (nLoop % 100000 == 0) {
// printf("here thread %d\n", *pID);
}
} while (nLoop < 1000000);
//printf("Thread%d was terminated Result:nAccount1 = %d, nAccount2 = %d\n", *pID, nAccount1, nAccount2);
flag++;
return 0;
}
DWORD WINAPI ThreadExecutive_2(LPVOID lpParameter) {
int nLoop = 0;
int nTemp1, nTemp2, nRandom;
int* pID = (int*)lpParameter;
printf("Thread: %d Built successfully!\n", *pID);
do {
Process[1] = 1;
Turn = 0;
while (Process[0] == 1 && Turn == 0);
nTemp1 = nAccount1;
nTemp2 = nAccount2;
nRandom = rand();
nAccount1 = nTemp1 + nRandom;
nAccount2 = nTemp2 - nRandom;
Process[1] = 0;
nLoop++;
if (nLoop % 100000 == 0) {
printf("here thread %d\n", *pID);
}
} while (nLoop < 1000000);
printf("Thread%d was terminated Result:nAccount1 = %d, nAccount2 = %d\n", *pID, nAccount1, nAccount2);
flag++;
return 0;
}
int main()
{
start = GetTickCount();
printf("===============Peterson Algorithm================\n");
HANDLE handle1, handle2;
int Thread1 = 1;
int Thread2 = 2;
//===========This is where the problem occourred===================
handle1 = CreateThread(NULL, 0, ThreadExecutive_1, &Thread1, 0, NULL);
SetThreadAffinityMask(handle1, 0x00000001);
handle2 = CreateThread(NULL, 0, ThreadExecutive_2, &Thread2, 0, NULL);
SetThreadAffinityMask(handle2, 0x00000001);
//===========This is where the problem occourred===================
if (handle1 == NULL) {
printf("Handle1 build failed\n");
exit(0);
}
if (handle2 == NULL) {
printf("Handle2 build failed\n");
exit(0);
}
CloseHandle(handle1);
CloseHandle(handle2);
while (1) {
if (flag == 2) {
break;
}
}
end = GetTickCount();
printf("Execution time : %d\n", (end - start));
system("pause");
return 0;
}
Here are the results. Without SetThreadAffinityMask():
===============Peterson Algorithm================
Thread: 1 Built successfully!
Thread: 2 Built successfully!
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
here thread 2
here thread 1
Thread1 was terminated Result:nAccount1 = -1621397855, nAccount2 = 1621397855
here thread 2
Thread2 was terminated Result:nAccount1 = -1583839139, nAccount2 = 1583839139
Execution time : 312
With SetThreadAffinityMask():(An infinite loop occurred)
===============Peterson Algorithm================
Thread: 2 Built successfully!
here thread 2
here thread 2
here thread 2
here thread 2
Thread: 1 Built successfully!
This is for an Operating Systems programming assignment. I'm attempting to read n number of files, use threads to search each file for a number of occurrences for a specific character.
./mycount j new.txt some.txt here.txt hello.txt
The output for my test code as is should be:
argumentCount: 6
threadCount: 4
pthread_create() for thread 0 returns: 0
Thread 1
pthread_create() for thread 1 returns: 0
Thread 2
pthread_create() for thread 2 returns: 0
Thread 3
pthread_create() for thread 3 returns: 0
Thread 4
However each execution of mycount is different, with the last thread usually not executing/printing. Either that or they'll print sporadically, in tandem, etc.
I'm attempting to utilize a mutex to ensure the integrity of my data but I'm not sure what's really happening behind the scenes.
How do I ensure that everything finishes the same way each time? The last thread always returns 0, but it sometimes won't execute the function I give it completely.
Code:
//GLOBALS
int occurrences = 0;
//PROTOTYPES
void *scanFile( void *filePtr );
//Initialize space for mutex.
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//Receive arguments from .exe call
void main ( int argumentCount, char *argumentVariables[] )
{
//Exit if argumentCount is > 50.
if (argumentCount > 50)
{
perror("Too many arguments. Enter less than 50.\n");
exit(EXIT_FAILURE);
}
printf("argumentCount: %d \n", argumentCount);
//Instantiate variables.
//i - iterator
//*newCommand - Used to hold string value of first command entered.
//*newVector - Used to hold string of the rest of the commands. Is a vector.
int i;
char *searchCharacter;
char *newVector[argumentCount];
//Iterate through command line arguments and split them.
for (i = 0; i < argumentCount; i++)
{
searchCharacter = argumentVariables[1];
if (i < argumentCount - 1)
{
newVector[i] = argumentVariables[1 + i];
}
else
{
newVector[i] = NULL;
}
}
//Exit if newest command is NULL.
if (searchCharacter == NULL)
{
perror("No character entered!\n");
exit(EXIT_FAILURE);
}
int threads = argumentCount - 2;
printf("threadCount: %d \n", threads);
pthread_t * thread = malloc(sizeof(pthread_t)*threads);
for (int i = 0; i < threads; i++)
{
int ret;
char *message = "Thread";
ret = pthread_create(&thread[i], NULL, scanFile, (void*) message);
if (ret != 0)
{
printf("Error - pthread_create() return code: %d\n", ret);
exit(EXIT_FAILURE);
}
printf("pthread_create() for thread %d returns: %d\n", i, ret);
}
exit(EXIT_SUCCESS);
}
void *scanFile( void *filePtr )
{
pthread_mutex_lock( &mutex );
char *message;
message = (char *) filePtr;
occurrences += 1;
printf("%s %d\n", message, occurrences);
pthread_mutex_unlock( &mutex );
}
Found the solution thanks to user2864740 and Ken Thomases.
Added:
for (int j = 0; j < threads; j++)
{
//Join the threads so all the data is good to go.
pthread_join(thread[j], NULL);
}
Correction:
for (int i = 0; i < threads; i++)
{
request[i].file = argumentVariables[i + 2];
request[i].character = searchCharacter;
//Create the thread. Any output from the integer newThread is an error code.
newThread = pthread_create(&thread[i], NULL, *scanFile, &request[i]);
if (newThread != 0)
{
printf("Error - pthread_create() return code: %d\n", newThread);
exit(EXIT_FAILURE);
}
}
for (int j = 0; j < threads; j++)
{
//Join the threads so all the data is good to go.
pthread_join(thread[j], NULL);
}
So two threads should call two runTimes functions and runTimes function should call increase_count and decrease_count. At the end the result should be 3. The problem is that the last line of code doesn't get executed when I run the program and I can't really identify what causes the race condition.
#define MAX_RESOURCES 5
int available_resources = MAX_RESOURCES;
int times = 100000;
pthread_mutex_t mutex;
sem_t semaphore;
/* decrease available_resources by count resources
* return 0 if sufficient resources available,
* otherwise return -1 */
int decrease_count(int count) {
if (available_resources < count) {
return -1;
} else {
available_resources -= count;
printf("Locked %i resources, now available: %i\n" , count , available_resources);
return 0;
}
}
/* increase available resources by count */
int increase_count(int count) {
if (count + available_resources > 5) {
return -1;
} else {
available_resources += count;
printf("Freed %i resources, now available: %i\n" , count , available_resources);
return 0;
}
}
void *runTimes(void *null) {
int i = 0 , result;
while (i < times) {
result = -1;
while (result < 0) {result = decrease_count(1);}
result = -1;
while (result < 0) {result = increase_count(1);}
i += 1;
printf("Count; %i\n",i );
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread1 , thread0;
pthread_t threads [2];
decrease_count(2);
pthread_create(&thread0, NULL, runTimes, NULL);
pthread_create(&thread1, NULL, runTimes, NULL);
int i = 0;
while( i < 2) {
pthread_join(threads[i], NULL);
i++;
}
pthread_exit(NULL);
printf("Currently available resources (should be 3): %i\n" , available_resources);
return 0;
}
the last line of code doesn't get executed
This is beacuse you call
pthread_exit(NULL);
before calling this
printf("Currently available resources (should be 3): %i\n" , available_resources);
(last) line.
pthread_exit() exits the current thread, that is the thread that calls function.
The race in the code you show is unrelated to this. It might occur because the code does not implement any protection against concurrently accessing the same variables.
Also you want to join the threads you created.
To do so change
pthread_create(&thread0, NULL, runTimes, NULL);
pthread_create(&thread1, NULL, runTimes, NULL);
to be
pthread_create(&threads[0], NULL, runTimes, NULL);
pthread_create(&threads[1], NULL, runTimes, NULL);
assume creating 3 worker threads by pthread_create,
in these worker thread routine, each call a simple infinite loop function which do not have a return to do counting
how to make worker thread gain control after calling infinite loop function and save the context of infinite loop function for calling in worker thread again?
Let me rephrase to see if I understood the problem.
You have a master thread which spawns 3 worker threads which each do a long running (infinite) job.
At a certain point you want to interrupt processing, save the state of all threads to resume where they left off at a later time.
I think the best way of doing this is organize your threads work in transactionally bound chunks. When restarting, you check the last completed transaction, and go from there.
But since I suspect this to be a homework assignment in low level thread plumbing, may i suggest a shared boolean which is checked on every time you go through the loop to exit and store the state afterwards. Aternatively "kill" the thread and catch the exception and store the state. The last option is messy.
I think you should clarify your question.
If every worker thread calls an infinite loop then I suppose that your master thread would have to call pthread_cancel() on each of them. From what I gather this might require calls to other pthread_*() functions to set the "cancelability" of the target threads.
Of course this suggestion begs the question. The vastly preferable approach would be to prevent those infinite loops. Write your code so that it has exit conditions ... so that the work is bounded by some sort of input or has some sort of event handling.
want to do the effect of a threadpool, after calling infinite loop function, each worker thread can change other tasks(other infinite loop function) to run
for example 3 worker thread can run 4 tasks(infinite loop functions)
#ifndef JOB_CPP
#define JOB_CPP
#include "job.h"
#define NUM_OF_TASKS 4
#define NUM_OF_WORKERS 3
void (* job_queue[NUM_OF_TASKS])(void*);
void (* fp[NUM_OF_WORKERS])(void*); // original running job
int running_task[NUM_OF_WORKERS];
int idle[NUM_OF_TASKS];
int last_running_task[NUM_OF_WORKERS];
int no_of_tasks_running[NUM_OF_WORKERS];
my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
void func1(void *arg)
{
int count = 0;
int status;
while(true)
{
//if((count % 100) == 0)
//printf("func1 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.cv);
}
}
void func2(void *arg)
{
int count = 0;
int status;
while(true)
{
//printf("func2 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.cv);
}
}
void func3(void *arg)
{ int count = 0;
int status;
while(true)
{
//printf("func3 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.cv);
}
}
void func4(void *arg)
{ int count = 0;
int status;
while(true)
{
//printf("func4 run %d\n", count);
count = count + 1;
//status = pthread_cond_signal(&data.done);
}
}
void jobinit()
{
for(int i=0; i<NUM_OF_TASKS; i++)
{
job_queue[i] = NULL;
idle[i] = 0;
}
for(int i=0; i<NUM_OF_WORKERS; i++)
{
fp[i] = NULL;
running_task[i] = 0;
last_running_task[i] = 0;
no_of_tasks_running[i] = 0;
}
jobadd(func1);
jobadd(func2);
jobadd(func3);
jobadd(func4);
jobrun();
}
void jobadd(void (*job)(void*))
{
for(int i=0; i<4; i++)
{
if(job_queue[i] == NULL)
{
job_queue[i] = job;
return;
}
}
}
void* workserver(void *arg);
void* workserver(void *arg)
{
int status, timedout;
struct timespec timeout;
status = pthread_mutex_lock(&data.mutex);
while(true)
{
timedout = 0;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 2;
sleep(1);
//void (* clean)(void*);
status = pthread_cond_timedwait(&data.cv, &data.mutex, &timeout);
if(status == ETIMEDOUT){
printf("worker wait timed out %d\n", (int)arg);
timedout = 1;
}else if(status != 0){
printf("worker wait failed %d\n", (int)arg);
status = pthread_mutex_unlock(&data.mutex);
return NULL;
}
printf("workserver number: %d\n", (int)arg);
status = pthread_mutex_unlock(&data.mutex);
printf("function run %d\n", (int)arg);
(* job_queue[(int)arg])(NULL);
printf("cond wait start %d\n", (int)arg);
status = pthread_cond_wait(&data.done, &data.mutex);
printf("cond wait end\n");
status = pthread_mutex_lock(&data.mutex);
}
}
void jobrun()
{
for(int i=0; i<3; i++) {idle[i] = 0;}
pthread_t r1_threadid[3];
for(int i=0; i<3; i++)
{
pthread_create(&r1_threadid[i], NULL, workserver, (void*)i);
}
int status;
struct timespec timeout;
timeout.tv_sec = time (NULL) + 2;
timeout.tv_nsec = 0;
while(true)
{
status = pthread_mutex_lock(&data.mutex);
while(data.value == 0)
{
status = pthread_cond_timedwait(&data.cond, &data.mutex, &timeout);
}
if(data.value != 0)
{
//printf("condition was signaled\n");
data.value = 0;
}
status = pthread_mutex_unlock(&data.mutex);
if(status != 0)
printf("unlock mutex error");
}
}
#endif