I am using ucontext along with pthread. The below program works OK on Linux, but has failed assertion on Mac.
The problem seems that thread local variables are not correctly accessed after resuming the context from another thread.
The program creates two threads, A and B. A sets the context ready before B could resume the context, for it's synced properly.
It's very appreciated if someone could shed some light on this behavior on mac.
ENV:
clang version 3.7.0 (http://llvm.org/git/llvm.git 8d70064a4ac2ae09b8003173e751cfad9dc15400)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
Program:
#define _XOPEN_SOURCE 800
#include <ucontext.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
static int flag = 0;
void swap(ucontext_t *old, ucontext_t *new)
{
int ret = swapcontext(old, new);
assert(ret == 0);
}
#define SSIZE MINSIGSTKSZ
static char stack[SSIZE];
static ucontext_t a_ctx[2];
static ucontext_t b_ctx[2];
volatile static __thread int bug = 0;
static void func(int b) { }
static void f1 (void)
{
assert(bug == 0);
func(bug);
swap(&a_ctx[1], &a_ctx[0]);
assert(bug == 1);
}
void *thread_a(void *arg)
{
printf("A is %lu\n", pthread_self());
bug = 0;
ucontext_t ctx = a_ctx[1];
getcontext(&ctx);
ctx.uc_stack.ss_sp = stack;
ctx.uc_stack.ss_size = sizeof stack;
makecontext(&ctx, f1, 0);
swap(&a_ctx[0], &ctx);
__atomic_store_n(&flag, 1, __ATOMIC_RELAXED);
sleep(1);
return NULL;
}
void *thread_b(void *arg)
{
printf("B is %lu\n", pthread_self());
bug = 1;
while(__atomic_load_n(&flag, __ATOMIC_RELAXED) == 0) ;
swap(&b_ctx[0], &a_ctx[1]);
return NULL;
}
int main(int argc, char **argv)
{
pthread_t a, b;
pthread_create(&b, NULL, &thread_b, NULL);
pthread_create(&a, NULL, &thread_a, NULL);
pthread_exit(NULL);
}
Related
I got this simple C program that uses pthreads.
I basically want to call my_function() once I'm 100% sure that my_thread() gets called and is executed.
I need to know how to synchronize the main() function and the my_thread() function.
Please note that the my_thread() never returns.
#include <stdio.h>
#include <pthread.h>
void my_function (void);
void* my_thread (void* arg);
int main (int argc, char* argv[])
{
int rc;
pthread_t id;
rc = pthread_create(&id, NULL, my_thread, NULL);
if (rc != 0)
{
return -10;
}
/*
* I wanna call my_function() once I'm 100% sure my_thread() gets called and being executed
*/
/*
* Synchronization code to add here:
*/
my_function();
return 0;
}
void* my_thread (void* arg)
{
/*
* This pthread never returns
*/
while (1)
{
/* stuff */
};
}
void my_function (void)
{
printf("Hello\n");
}
Thanks for your help.
Can anybody check if this solution is correct?
It works using the debugger but I would like to have a comment from experienced programmers.
#include <stdio.h>
#include <pthread.h>
void my_function (void);
void* my_thread (void* arg);
int started;
pthread_mutex_t mutex;
pthread_t id;
int main (int argc, char* argv[])
{
int rc;
int done;
started = 0;
mutex = PTHREAD_MUTEX_INITIALIZER;
rc = pthread_create(&id, NULL, my_thread, NULL);
if (rc != 0)
{
return -10;
}
/*
* Synchronization code proposed:
*/
done = 0;
do
{
pthread_mutex_lock(&mutex);
if (started == 1)
{
done = 1;
}
pthread_mutex_unlock(&mutex);
}
while (done == 0);
/*
* I wanna call my_function() once I'm 100% sure
* that my_thread() is called and being executed
*/
my_function();
return 0;
}
void* my_thread (void* arg)
{
started = 1;
while (1)
{
/* stuff */
};
}
void my_function (void)
{
printf("Hello\n");
}
I have this assignment for Operating Systems, the code won't run in MAC terminal, I keep getting an issue that says, "Image". Is there any help I can get on this issue?
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
// These two functions will run concurrently
void* print_i(void *ptr)
{
printf("I am in i\n");
}
void* print_j(void *ptr)
{
printf("I am in j\n");
}
int main()
{
pthread_t t1,t2;
int rc1 = pthread_create(&t1, NULL, print_i, NULL);
int rc2 = pthread_create(&t2, NULL, print_j, NULL);
exit(0);
}
The keyword void (not a pointer) means "nothing" in C. This is consistent.
As you noted, void* means "pointer to anything" in languages that support raw pointers (C and C++). This means you need to return something.
This is the reason why you get this type of warning.
If you return someting, like return 0; warnings disapear.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
// These two functions will run concurrently
void* print_i(void *ptr)
{
printf("I am in i\n");
return 0;
}
void* print_j(void *ptr)
{
printf("I am in j\n");
return 0;
}
int main()
{
pthread_t t1,t2;
int rc1 = pthread_create(&t1, NULL, print_i, NULL);
int rc2 = pthread_create(&t2, NULL, print_j, NULL);
exit(0);
}
You can learn more about it here:
https://linux.die.net/man/3/pthread_create
In the sample below, I tried to modify a char pointer in the main process using pthread. However, I dont see the pointer value changed. What is the reason and how can I achieve my goal?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>
#include <errno.h>
#include <string.h>
char *target = "thread";
void *modify(void *vargp) {
vargp = target;
printf("Thread vargp = %s\n", (char*)vargp);
return NULL;
}
int main() {
char *pt = "main";
pthread_t thread_id;
printf("Before Thread, pt = %s\n", pt);
pthread_create(&thread_id, NULL, modify, pt);
pthread_join(thread_id, NULL);
printf("After Thread, pt = %s\n", pt);
exit(0);
}
$ ./pthread_simple
Before Thread, pt = main
Thread vargp = thread
After Thread, pt = main
What I want to achieve is:
$ ./pthread_simple
Before Thread, pt = main
Thread vargp = thread
After Thread, pt = thread
Function arguments are copies of what are passed and change to them is local to the functions. To have functions modify things, you have to pass pointers to what should be modified.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>
#include <errno.h>
#include <string.h>
char *target = "thread";
void *modify(void *vargp) {
*(char**)vargp = target; /* add cast and dereference to modify what is pointed */
printf("Thread vargp = %s\n", *(char**)vargp); /* add cast and dereference */
return NULL;
}
int main() {
char *pt = "main";
pthread_t thread_id;
printf("Before Thread, pt = %s\n", pt);
pthread_create(&thread_id, NULL, modify, &pt); /* pass pointer to pt */
pthread_join(thread_id, NULL);
printf("After Thread, pt = %s\n", pt);
exit(0);
}
It gets me error at rand_r
undefined reference to 'rand_r'
It is my first program at c language
I must use rand_r to threads, but i don't know what to do.
Please help me. Thank you
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "p3160062.h"
int cook;
int oven;
int prep;
int bake;
pthread_mutex_t lock;
pthread_t thread_id[100];
unsigned int seed;
int a;
void *myThread(void *vargp)
{
pthread_mutex_lock(&lock);
a=rand_r(&seed)%6;
while(a==0){
a=rand_r(&seed)%6;
}
printf("a=%d\n",a);
sleep(1);
printf("In thread\n");
pthread_mutex_unlock(&lock);
return NULL;
}
int main(void)
{
seed=1;
int i=0;
printf("Before Thread\n");
for(i=0;i<100;i++){
pthread_create(&(thread_id[i]), NULL, myThread, NULL);
pthread_join(thread_id[i], NULL);
seed++;
}
printf("After Thread\n");
pthread_mutex_destroy(&lock);
exit(0);
}
I am making a program containing a "Server.c" which waits a client to send it a SIGUSR1 msg 10 times, then dies, and a "client.c" which sends a SIGUSR1 msg to the server.
The problem is that if I try to access the siginfo_t* info, I get a segmentation fault.
Note that this is being tested on a Debian ssh server on which I do not have high permissions.
Node that this code works fine on Ubuntu.
Can siginfo_t *info fail due to permission issues? Or is there another issue causing this portability problem. As far as I know libc should be fairly standard throughout any linux distro, possibly unix.
Any Ideas?
Thanks
server.c
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int counter = 0;
pid_t *clients = 0;
void on_signal(int signo, siginfo_t *info, void * context)
{
puts("SIGNAL RECEIVED");
assert(clients);
clients[counter] = info->si_pid;
++counter;
}
int main()
{
struct sigaction action;
sigset_t set;
int recieveflag = 0;
clients = (pid_t*)malloc(10 * sizeof(pid_t));
sigemptyset(&set);
sigaddset(&set, SA_SIGINFO);
memset(&action, 0, sizeof(struct sigaction));
action.sa_sigaction = on_signal;
sigaction(SIGUSR1, &action, 0);
while (counter < 10) {
//sigprocmask(SIG_BLOCK, &set, 0);
sigsuspend(&set);
}
puts("I'm done!");
return 0;
}
client.c:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int main(int argc, const char** argv)
{
int server_id;
assert(argc == 2);
server_id = atoi(argv[1]);
assert(server_id > 0);
kill(server_id, SIGUSR1);
return 0;
}
I tried editing server.c to:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int counter = 0;
pid_t *clients = 0;
void on_signal(int sig)
{
puts("SIGNAL RECEIVED");
}
int main()
{
struct sigaction action;
sigset_t set;
int recieveflag = 0;
clients = (pid_t*)malloc(10 * sizeof(pid_t));
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
memset(&action, 0, sizeof(struct sigaction));
action.sa_flags = SA_SIGINFO;
action.sa_handler = on_signal;
sigaction(SIGUSR1, &action, 0);
while (counter < 10) {
sigprocmask(SIG_BLOCK, &set, 0);
sigsuspend(&set);
++counter;
}
puts("I'm done!");
return 0;
}
now it no longer receives the SIGUSR1 event at all.
The basic behavior of sigaction is to call a simple callback like : void (*sa_handler)(int);. So if you want to use the sigaction handle with 3 parameters void (*sa_sigaction)(int, siginfo_t *, void *);, you must set the sa_flags field of your struct sigaction with the flag SA_SIGINFO. Take a look of the man page : http://www.kernel.org/doc/man-pages/online/pages/man2/sigaction.2.html who is clear.