So I am new to system programming and learning threads.What does the term posix means? I need help in understanding the following code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_message_function( void *ptr );
main()
{
pthread_t thread1, thread2;
const char *message1 = "Thread 1";
const char *message2 = "Thread 2";
int iret1, iret2;
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
printf("Thread 1 returns: %d\n",iret1);
printf("Thread 2 returns: %d\n",iret2);
exit(0);
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}
I dont understand the line: pthread_join( thread1, NULL);
and the function: void *print_message_function( void *ptr ).
Also, what does the variable iret returns?
It spawns two threads.
Saves their "return values" to variables previously declared.
Joins to threads, basically waits for them to stop.
Prints the variables
exits with status 0, normal successful exit
posix is a general standard for Unix like operating systems. E.g file structure etc
You should read posix documentation.
I dont understand the line: pthread_join( thread1, NULL); and the
function: void *print_message_function( void *ptr ).
pthread_join blocks until the thread terminates
void *print_message_function( void *ptr ) is a function returning void* and receiving a void* as parameter
Again, you should read posix documentation (and learn more C).
Related
The Linux robust_list mechanism is a tool used by robust mutexes to support automatic unlocking in the event that the lock owner fails to unlock before terminating, maybe due to unexpected death. According to man set_robust_list:
The purpose of the robust futex list is to ensure that if a thread accidentally fails to unlock a futex before terminating or calling execve(2), another thread that is waiting on that futex is notified that the former owner of the futex has died. This notification consists of two pieces: the FUTEX_OWNER_DIED bit is set in the futex word, and the kernel performs a futex(2) FUTEX_WAKE operation on one of the threads waiting on the futex.
This is not the behavior I'm seeing.
I'm seeing the futex replaced with FUTEX_OWNER_DIED, not ored with.
And I'm not getting the FUTEX_WAKE call.
#include <chrono>
#include <thread>
#include <linux/futex.h>
#include <stdint.h>
#include <stdio.h>
#include <syscall.h>
#include <unistd.h>
using ftx_t = uint32_t;
struct mtx_t {
mtx_t* next;
mtx_t* prev;
ftx_t ftx;
};
thread_local robust_list_head robust_head;
void robust_init() {
robust_head.list.next = &robust_head.list;
robust_head.futex_offset = offsetof(mtx_t, ftx);
robust_head.list_op_pending = NULL;
syscall(SYS_set_robust_list, &robust_head.list, sizeof(robust_head));
}
void robust_op_start(mtx_t* mtx) {
robust_head.list_op_pending = (robust_list*)mtx;
__sync_synchronize();
}
void robust_op_end() {
__sync_synchronize();
robust_head.list_op_pending = NULL;
}
void robust_op_add(mtx_t* mtx) {
mtx_t* old_first = (mtx_t*)robust_head.list.next;
mtx->prev = (mtx_t*)&robust_head;
mtx->next = old_first;
__sync_synchronize();
robust_head.list.next = (robust_list*)mtx;
if (old_first != (mtx_t*)&robust_head) {
old_first->prev = mtx;
}
}
int futex(ftx_t* uaddr,
int futex_op,
int val,
uintptr_t timeout_or_val2,
ftx_t* uaddr2,
int val3) {
return syscall(SYS_futex, uaddr, futex_op, val, timeout_or_val2, uaddr2, val3);
}
int ftx_wait(ftx_t* ftx, int confirm_val) {
return futex(ftx, FUTEX_WAIT, confirm_val, 0, NULL, 0);
}
int main() {
mtx_t mtx = {0};
std::thread t0{[&]() {
fprintf(stderr, "t0 start\n");
ftx_wait(&mtx.ftx, 0);
fprintf(stderr, "t0 done\n");
}};
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::thread t1{[&]() {
fprintf(stderr, "t1 start\n");
robust_init();
robust_op_start(&mtx);
__sync_bool_compare_and_swap(&mtx.ftx, 0, syscall(SYS_gettid));
robust_op_add(&mtx);
robust_op_end();
fprintf(stderr, "t1 ftx: %x\n", mtx.ftx);
fprintf(stderr, "t1 done\n");
}};
t1.join();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
fprintf(stderr, "ftx: %x\n", mtx.ftx);
t0.join();
}
Running
g++ -o ./example ~/example.cpp -lpthread && ./example
prints something like:
t0 start
t1 start
t1 ftx: 12ea65
t1 done
ftx: 40000000
and hangs.
I would expect the final value of the futex to be 4012ea65 and for thread 0 to unblock after thread 1 completes.
here I come again with a new question for this (blasted) threads programming.
Here is my code, hope you can help me understand what's wrong with it (keep in mind I had to write this code again, not copy-paste, so there may be some type errors - the compiled code is ok and works, so the problem is not the syntax).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int i=0;
void *TFun(void *TArg)
{
printf("THREAD i=%d\n", i);
i++;
return NULL;
}
int main()
{
pthread_t TID;
TID=pthread_create(&TID, NULL, TFun, NULL);
pthread_join(TID, NULL);
printf("THREAD i=%d\n", i);
i++;
exit(0);
}
I expect this to print "THREAD i=0" and then "MAIN i=1", but this doesn't happen. it only prints "MAIN i=0", the Thread is not executed.
https://i.ibb.co/Y0KYWCK/code.png
https://i.ibb.co/pznZ3TT/result.png
The value of TID is normally written by reference within pthread_create(), but was also being overwritten with the int return value; change to an added int variable:
(old)
TID=pthread_create(&TID, NULL, TFun, NULL);
(new)
int pcr;
pcr = pthread_create(&TID, NULL, TFun, NULL);
I'm using pthread_create to use a function from shared library. I receive Segmenation fault after the following code executes:
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include<string.h>
#include<pthread.h>
#include<unistd.h>
void (*GetVersion)(char *version);
void* draw(void *arg)
{
void *handle;
char *error;
handle = dlopen ("libOpenKaillera.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
GetVersion = dlsym(handle, "GetVersion");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
char version[4];
kailleraGetVersion(version);
puts(version);
dlclose(handle);
return NULL;
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, &draw, NULL);
sleep(5000);
return 0;
}
The backtrace command says the following:
#0 0xb68e7be0 in ?? ()
#1 0xb7fa9d56 in __nptl_deallocate_tsd () at pthread_create.c:158
#2 0xb7fa9f83 in start_thread (arg=0xb7df0b40) at pthread_create.c:325
#3 0xb7ede4ce in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
I don't understand what a reason can cause this. Can you help me please?
after each calling of pthread_create, please remember to call pthread_join or pthread_detach to tell the thread how to perform termination. normally, please call pthread_join before exiting the creating thread (in this case, it is function main).
Can anyone shed light on the reason that when the below code is compiled and run on OSX the 'bartender' thread skips through the sem_wait() in what seems like a random manner and yet when compiled and run on a Linux machine the sem_wait() holds the thread until the relative call to sem_post() is made, as would be expected?
I am currently learning not only POSIX threads but concurrency as a whole so absoutely any comments, tips and insights are warmly welcomed...
Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
//using namespace std;
#define NSTUDENTS 30
#define MAX_SERVINGS 100
void* student(void* ptr);
void get_serving(int id);
void drink_and_think();
void* bartender(void* ptr);
void refill_barrel();
// This shared variable gives the number of servings currently in the barrel
int servings = 10;
// Define here your semaphores and any other shared data
sem_t *mutex_stu;
sem_t *mutex_bar;
int main() {
static const char *semname1 = "Semaphore1";
static const char *semname2 = "Semaphore2";
pthread_t tid;
mutex_stu = sem_open(semname1, O_CREAT, 0777, 0);
if (mutex_stu == SEM_FAILED)
{
fprintf(stderr, "%s\n", "ERROR creating semaphore semname1");
exit(EXIT_FAILURE);
}
mutex_bar = sem_open(semname2, O_CREAT, 0777, 1);
if (mutex_bar == SEM_FAILED)
{
fprintf(stderr, "%s\n", "ERROR creating semaphore semname2");
exit(EXIT_FAILURE);
}
pthread_create(&tid, NULL, bartender, &tid);
for(int i=0; i < NSTUDENTS; ++i) {
pthread_create(&tid, NULL, student, &tid);
}
pthread_join(tid, NULL);
sem_unlink(semname1);
sem_unlink(semname2);
printf("Exiting the program...\n");
}
//Called by a student process. Do not modify this.
void drink_and_think() {
// Sleep time in milliseconds
int st = rand() % 10;
sleep(st);
}
// Called by a student process. Do not modify this.
void get_serving(int id) {
if (servings > 0) {
servings -= 1;
} else {
servings = 0;
}
printf("ID %d got a serving. %d left\n", id, servings);
}
// Called by the bartender process.
void refill_barrel()
{
servings = 1 + rand() % 10;
printf("Barrel refilled up to -> %d\n", servings);
}
//-- Implement a synchronized version of the student
void* student(void* ptr) {
int id = *(int*)ptr;
printf("Started student %d\n", id);
while(1) {
sem_wait(mutex_stu);
if(servings > 0) {
get_serving(id);
} else {
sem_post(mutex_bar);
continue;
}
sem_post(mutex_stu);
drink_and_think();
}
return NULL;
}
//-- Implement a synchronized version of the bartender
void* bartender(void* ptr) {
int id = *(int*)ptr;
printf("Started bartender %d\n", id);
//sleep(5);
while(1) {
sem_wait(mutex_bar);
if(servings <= 0) {
refill_barrel();
} else {
printf("Bar skipped sem_wait()!\n");
}
sem_post(mutex_stu);
}
return NULL;
}
The first time you run the program, you're creating named semaphores with initial values, but since your threads never exit (they're infinite loops), you never get to the sem_unlink calls to delete those semaphores. If you kill the program (with ctrl-C or any other way), the semaphores will still exist in whatever state they are in. So if you run the program again, the sem_open calls will succeed (because you don't use O_EXCL), but they won't reset the semaphore value or state, so they might be in some odd state.
So you should make sure to call sem_unlink when the program STARTS, before calling sem_open. Better yet, don't use named semaphores at all -- use sem_init to initialize a couple of unnamed semaphores instead.
I have created a thread. The main function is creating an element and appending it to the Tail/End of a queue. The thread is reading the list from Head/Start and is releasing the memory after.
I have the following code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *print_message_function( void *ptr );
typedef struct stCheckFree
{
char name[30];
int doneflag;
struct stCheckFree *next;
}CheckFree;
CheckFree *gHead=NULL;
CheckFree *gTail=NULL;
int main()
{
pthread_t thread1;
char *message1 = "Thread 1";
int iret1;
unsigned long TestCount=1;
CheckFree *pCurr=NULL;
CheckFree *pTemp=NULL;
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
while(1)
{
pCurr=malloc(sizeof(CheckFree));
memset(pCurr,0,sizeof(CheckFree));
printf("Malloc\n");
sprintf(pCurr->name,"Test-%ld",TestCount); TestCount++;
pCurr->doneflag=0;
pCurr->next=NULL;
pTemp=gTail;
gTail=pCurr;
if(pTemp) pTemp->next=gTail;
if(!gHead)
{
gHead=gTail;
}
}
return 0;
}
void *print_message_function( void *ptr )
{
CheckFree *pTrav;
while(1)
{
pTrav=gHead;
if(pTrav)
{
printf("[%s]\n",pTrav->name);
pTrav->doneflag=1;
gHead=gHead->next;
free(pTrav);
}
}
}
When I run the code its giving me a segfault. What might be the issue?
Please help!
Thanks.
PS- If i remove the free(), its running splendidly!!!
-----------------------------------------------------------------------------------
---EDIT 1---
-----------------------------------------------------------------------------------
I am not sure if this is the fix, but I need more inputs from other stackoverflow members.
void *print_message_function( void *ptr )
{
CheckFree *pTrav;
while(1)
{
pTrav=gHead;
if(pTrav)
{
printf("[%s]\n",pTrav->name);
pTrav->doneflag=1;
gHead=gHead->next;
if(!gHead) gTail=NULL; /* NEW CODE */
free(pTrav);
sleep(0.7);
}
}
}
Please help as it is important! :)
Thanks again.
-----------------------------------------------------------------------------------
---EDIT 2---
-----------------------------------------------------------------------------------
The code change:-
if(!gHead) gTail=NULL; /* NEW CODE */
is destroying data by re-initializing NULL over it.
You can see it by just doing the following code changes:
...pTemp=gTail;
gTail=pCurr;
if(pTemp) pTemp->next=gTail;
if(!gTail)printf("Data lost\n");
if(!gHead)
{...
Please help me to rectify this issue...
-----------------------------------------------------------------------------------
---EDIT 3---
-----------------------------------------------------------------------------------
Following #wazy's recommendation of using mutex lock I updated the code as follows:-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void * thread_function( void *ptr );
typedef struct stCheckFree
{
char name[30];
int doneflag;
struct stCheckFree *next;
}CheckFree;
pthread_mutex_t lock; // EDIT 3
CheckFree *gHead=NULL;
CheckFree *gTail=NULL;
int main()
{
pthread_t thread1;
char *message1 = "Thread 1";
int iret1;
unsigned long TestCount=1;
CheckFree *pCurr=NULL;
CheckFree *pTemp=NULL;
if (pthread_mutex_init(&lock, NULL) != 0) // EDIT 3
{
printf("\n mutex init failed\n");
return 1;
}
iret1 = pthread_create( &thread1, NULL, thread_function, (void*) message1);
while(1)
{
pCurr=malloc(sizeof(CheckFree));
memset(pCurr,0,sizeof(CheckFree));
sprintf(pCurr->name,"Test-%ld",TestCount); TestCount++;
pCurr->doneflag=0;
pCurr->next=NULL;
pTemp=gTail;
gTail=pCurr;
if(pTemp) pTemp->next=gTail;
//pthread_mutex_lock(&lock); // EDIT 3(commented out)
if(!gHead)
{
pthread_mutex_lock(&lock); // EDIT 4
gHead=gTail;
pthread_mutex_unlock(&lock); // EDIT 4
}
//pthread_mutex_unlock(&lock); // EDIT 3(commented out)
}
pthread_join( thread1, NULL);
printf("Thread 1 returns: %d\n",iret1);
return 0;
}
void * thread_function( void *ptr )
{
CheckFree *pTrav;
while(1)
{
pTrav=gHead;
if(pTrav)
{
//printf("[%s]\n",pTrav->name);
pTrav->doneflag=1;
gHead=gHead->next;
if(!gHead) sleep(1);//gTail=NULL;
free(pTrav);
}
}
}
Am I on the right track?????
Thanks!!!
Running your code gives me double free or corruption (fasttop) from glibc. Looking at your code I see that you are using both gHead in your thread1 and in your main thread. It seems to be a multithreading synchronization problem.