I have following code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* a(void* ptr) {
while(1){
printf("1");
printf("2");
printf("3");
printf("4");
}
}
int main(int argc, char** argv) {
pthread_t t;
pthread_create(&t, NULL, a, 0);
while(1){
printf("a");
printf("b");
printf("c");
printf("d");
}
pthread_join(t, NULL);
return 0;
}
the result of this code is "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd1234123412341234..........."
but I want them to be mixed like "ab12c3d4a1bcda23b......"
how can I configure the scheduling time slice of a thread?
is this possible?
thank you in advance
You can modify scheduling behaviour by setting the sched param (pthread_setschedparam(3)) to for example SCHED_RR (RR means Round Robin). There is SCHED_FIFO, SCHED_RR and SCHED_OTHER with SCHED_OTHER being the default.
Related
Assume the code below demonstrating a binary semaphore example.
In this example, we have a pthread that reads the source.txt and attempts to copy the content to destination.txt while locking it using a binary semaphore.
What happens in the comment section below without the semaphore?
#include <cstdlib>
#include <memory>
#include <filesystem>
#define _TIMESPEC_DEFINED
#include <pthread.h>
#include <semaphore.h>
#include <thread>
#include <valarray>
pthread_t StartFileAccessThread();
void *CopyFile(void *parameters);
int main(int argc, char* argv[])
{
pthread_t thread = StartFileAccessThread();
void *returnValue;
pthread_join(thread, &returnValue);
getchar();
return EXIT_SUCCESS;
}
pthread_t StartFileAccessThread()
{
std::string sourcePath("source.txt");
std::string destinationPath("dest.txt");
sem_t semaphore;
sem_init(&semaphore, 0, 0);
pthread_t thread;
void *parameters[3];
parameters[0] = &semaphore;
parameters[1] = &sourcePath;
parameters[2] = &destinationPath;
pthread_create(&thread, nullptr, &CopyFile, parameters);
// What happens without the binary semaphore?
sem_wait(&semaphore);
sem_destroy(&semaphore);
printf("Freeing ressources.\n");
return thread;
}
void *CopyFile(void *rawParameter)
{
void **parameters = static_cast<void **>(rawParameter);
sem_t *semaphore = static_cast<sem_t *>(parameters[0]);
std::string sourcePath(*static_cast<std::string *>(parameters[1]));
std::string destinationPath(*static_cast<std::string *>(parameters[2]));
sem_post(semaphore);
std::this_thread::sleep_for(std::chrono::seconds(2));
copy_file(sourcePath, destinationPath, std::experimental::filesystem::copy_options::overwrite_existing);
printf("File copied \n");
return nullptr;
}
What happens in the comment section below without the semaphore?
Without the semaphore, function startFileAccessThread() may return before the new thread finishes (or starts) copying its parameters from the argument object. That object is local to startFileAccessThread(), so its lifetime ends when that function returns. Undefined behavior results if the copy thread's accesses to it do not happen before that.
Problem
I wish to be able to pause the execution of a thread from a different thread. Note the thread paused should not have to cooperate. The pausing of the target thread does not have to occur as soon as the pauser thread wants to pause. Delaying the pausing is allowed.
I cannot seem to find any information on this, as all searches yielded me results that use condition variables...
Ideas
use the scheduler and kernel syscalls to stop the thread from being scheduled again
use debugger syscalls to stop the target thread
OS-agnostic is preferable, but not a requirement. This likely will be very OS-dependent, as messing with scheduling and threads is a pretty low-level operation.
On a Unix-like OS, there's pthread_kill() which delivers a signal to a specified thread. You can arrange for that signal to have a handler which waits until told in some manner to resume.
Here's a simple example, where the "pause" just sleeps for a fixed time before resuming. Try on godbolt.
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
void safe_print(const char *s) {
int saved_errno = errno;
if (write(1, s, strlen(s)) < 0) {
exit(1);
}
errno = saved_errno;
}
void sleep_msec(int msec) {
struct timespec t = {
.tv_sec = msec / 1000,
.tv_nsec = (msec % 1000) * 1000 * 1000
};
nanosleep(&t, NULL);
}
void *work(void *unused) {
(void) unused;
for (;;) {
safe_print("I am running!\n");
sleep_msec(100);
}
return NULL;
}
void handler(int sig) {
(void) sig;
safe_print("I am stopped.\n");
sleep_msec(500);
}
int main(void) {
pthread_t thr;
pthread_create(&thr, NULL, work, NULL);
sigset_t empty;
sigemptyset(&empty);
struct sigaction sa = {
.sa_handler = handler,
.sa_flags = 0,
};
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
for (int i = 0; i < 5; i++) {
sleep_msec(1000);
pthread_kill(thr, SIGUSR1);
}
pthread_cancel(thr);
pthread_join(thr, NULL);
return 0;
}
Look at this Unix C program:
#include <stdio.h>
#include <signal.h>
void handler(int signum)
{
printf("Handler signum=%d\n",signum);
}
int main(int argc, char *argv)
{
printf("Start\n");
signal(SIGFPE, handler);
int i=10/0;
printf("Next\n");
return 0;
}
As you can see, i am connecting SIGFPE to an handler.
Then, i make a DIV0 erreur.
The handler is fired, that is great.
But, this handler is called in loop !
Why ?
Thanks
If you simply return from your handler, execution resumes at the point where the signal was thrown, which results in another divide by zero error, which results in the handler being called again, and so on. You need to arrange for execution to continue at some other point in the code. The traditional approach is to use setjmp/longjmp, something like this
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
jmp_buf buf;
void handler(int signum)
{
longjmp(buf, signum);
}
int main(int argc, char *argv)
{
int rc = setjmp(buf);
if (rc == 0) {
printf("Start\n");
signal(SIGFPE, handler);
int i=10/0;
}
printf("Handler signum=%d\n", rc);
printf("Next\n");
return 0;
}
Note: this approach is very old school, and probably someone can suggest a better way to handle it. Also, you are probably better off calling sigaction rather than signal, as the semantics of signal are not consistent across different versions of Unix.
I am running two processes (Process A and B) on the same core. Process B is multithreaded in which one thread is sending Signal to the next thread to wake it and start its work. At a time, only one thread of process B can run on the common core.
**//Process A**
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
int main(int argc, char const *argv[])
{
struct timeval tval_result;
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(2, &my_set);
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
long int loopNum;
while(1)
{
gettimeofday(&tval_result, NULL);
printf("Dummy Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);
//for(loopNum = 1; loopNum <= 100000; loopNum++);
//printf("Dummy!!! # \n");
}
return 0;
}
Following is the code of Process B.
//Import
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#define NUM_THREADS 100
//global variables
pthread_cond_t condA[NUM_THREADS+1] = PTHREAD_COND_INITIALIZER;
pthread_cond_t condB = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t tid[NUM_THREADS];
int state = 0;
void *threadA(void *data_)
{
int i = 0, rValue;
long int loopNum;
int turn = (intptr_t)data_;
struct timeval tval_result;
while(1)
{
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(2, &my_set);
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
/* Wait for state A */
pthread_mutex_lock(&mutex);
// while (state != STATE_A)
if(state != turn)
{
pthread_cond_wait(&condA[turn], &mutex);
}
pthread_mutex_unlock(&mutex);
//do stuff
gettimeofday(&tval_result, NULL);
printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);
//for(loopNum = 1; loopNum <= 10000000000; loopNum++);
//printf("Hello Thread # %d\n", turn);
/* Set state TRUE for next thread */
pthread_mutex_lock(&mutex);
state = (state +1)%NUM_THREADS;
pthread_cond_signal(&condA[state]);
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, char *argv[])
{
int data = 0;
int err;
while(data < NUM_THREADS)
{
//create our threads
err = pthread_create(&tid[data], NULL, threadA, (void *)(intptr_t)data);
if(err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread created successfully\n");
data++;
}
pthread_exit(NULL);
}
I want to interleave the execution of process B in between threads of Process A for a very short duration (less than 1 microseconds). So, when thread i of process B finishes its work it'll send the signal to the next thread i+1 and in between, I want process A to come. This should be repeated for the rest of the course of execution.
When I am running above programs, process A is not able to come in between threads of the Process B. Is there any mechanism by which I can send signal with some timer so that signal does not reach the next thread immediately (and hence Process A comes for some time between two consecutive threads.)
There's no way you can force the Linux scheduler at that level.
You'll have to "signal" process A and then let it "signal" the other B thread.
But to "signal" may be a user space mechanism like spinning on a variable in shared memory.
I'd suggest you first try it with normal signals (going through the kernel) and see is the latency good enough. Only if it's too long, go play with spinning in user space.
Don't expect all that to work always under 1us. You'll probably get lots of jitter will have to move processes away from that core to reduce it, regardless of spinning or using kernel signalling.
For kernel signalling you may also use sockets, pipes, futexes,...
Now my question is, if you're running all that on one core, as you said, why not run it as a single thread - Just have one thread call B1, then A, then B2?
#include <pthread.h>
#ifndef __linux__
#include <windows.h>// to include the windows.h library//
#endif
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
#include <sys/timeb.h>
void *PrintHello(void *threadid)
{
srand(time(NULL));
long tid,a;
tid = (long)threadid;
a=rand()%5;
printf("Hello World! It's me, thread #%ld!%ld\n", tid,a);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t,a;
srand(time(NULL));
for(t=0; t<NUM_THREADS; t++){
a=rand()%5;
printf("In main: creating thread %ld,%ld\n", t,a);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
Alright I have this simple code and when I compile it inside the main() the random numbers
are different from one another but when i try to generate random numbers inside the threads, all the numbers that are produced are the same.
Try seeding from outside the threads. The problem is that you get the same seed for each thread