Modify this program so that it used User Level Thread(using -pthread library) /*
ID: 3835193 • Letter: M
Question
Modify this program so that it used User Level Thread(using -pthread library)
/*
3 users use the DB (for each, a thread is spawned).
Thread i does queryNo[i] queries for its user.
A global "total_queries" is maintained. Each thread
updates it after each of its queries.
This has a race condition on variable total_queries.
Note that if you have maxed out your allotted clones, one (or more)
child may never execute its function, although it exists. So
parent can't terminate because it waits forever for child
(do ps -lu USERID and kill the offending child)
*/
#define _GNU_SOURCE //for Ubuntu
#include <unistd.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
int queryNo[3]={1011,1012,1013};
int total_queries = 0;
int userThread (void *p) {
int i;
int q = (int)(long)p;
//set thread q on CPU q
cpu_set_t set;
CPU_ZERO( &set );
CPU_SET( q, &set );
if (sched_setaffinity( getpid(), sizeof( cpu_set_t ), &set ))
{
perror( "sched_setaffinity" );
_exit(0);
}
for (i=0;i total_queries=total_queries+1;
}
_exit(0);
}
int main(int argc, char *argv[]) {
const int STACK_SIZE = 65536;
char *stack;
char *stackTop[3];
pid_t cret[3], wret;
int i;
for (i=0;i<3;i++) { //do 3 child threads
stack = malloc(STACK_SIZE);
if (stack == NULL) {
perror("malloc"); exit(1);
}
stackTop[i] = stack + STACK_SIZE; /* Assume stack grows downward */
cret[i]=clone(userThread, stackTop[i], CLONE_VM|SIGCHLD, (void *)(long)i); //make child signal when done
if (cret[i]==-1) {perror("clone"); exit(0); }
//parent keeps going here
}
//for (i=0;i<3;i++) waitpid(cret[i],0,0);
for (i=0;i<3;i++) {
wret=waitpid(-1,0,0);
if (wret == -1) {
perror("waitpid");
exit(3);
} //a useless double-check that we got our own children...
if (wret != cret[0] && wret != cret[1] && wret != cret[2] ) {
perror("waitpid wret");
exit(2);
}
}
sleep(1);
printf("%d total_queries should be 3036 and it is %d ",getpid(), total_queries);
return 0;
}
-you can join threads much more simply. Actually, you HAVE to, given
this statement from "man
There is no pthreads analog of waitpid(-1, &status, 0), that is, "join with any termi-
nated thread". If you believe you need this functionality, you probably need to
rethink your application design.
Try to verify that the same race condition can also occur in your lab05q1 program.
(i.e., if you have time, run it until you see it print the "wrong" output.)
Note to see how to get a thread's TID in pthreads, see this example
/*From http://www.alexonlinux.com/multithreaded-simple-data-type-access-and-atomic-variables
The increment of global variable in line 41 is a race condition
compile with -pthread
*/
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include
#include
#include
#include
#include
#include
#include
#include
#define INC_TO 1000000 // one million...
int global_int = 0;
pid_t gettid( void )
{
return syscall( __NR_gettid );
}
void *thread_routine( void *arg )
{
int i;
int proc_num = (int)(long)arg;
cpu_set_t set;
CPU_ZERO( &set );
CPU_SET( proc_num, &set );
if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
{
perror( "sched_setaffinity" );
return NULL;
}
for (i = 0; i < INC_TO; i++)
{
global_int++;
// __sync_fetch_and_add( &global_int, 1 );
}
return NULL;
}
int main()
{
int procs = 0;
int i;
pthread_t *thrs;
// Getting number of CPUs
procs = (int)sysconf( _SC_NPROCESSORS_ONLN );
if (procs < 0)
{
perror( "sysconf" );
return -1;
}
thrs = malloc( sizeof( pthread_t ) * procs );
if (thrs == NULL)
{
perror( "malloc" );
return -1;
}
printf( "Starting %d threads... ", procs );
for (i = 0; i < procs; i++)
{
if (pthread_create( &thrs[i], NULL, thread_routine,
(void *)(long)i ))
{
perror( "pthread_create" );
procs = i;
break;
}
}
for (i = 0; i < procs; i++)
pthread_join( thrs[i], NULL );
free( thrs );
printf( "After doing all the math, global_int value is: %d ",
global_int );
printf( "Expected value is: %d ", INC_TO * procs );
return 0;
}
Explanation / Answer
int global_int = 0;
pid_t gettid( void )
{
return syscall( __NR_gettid );
}
void *thread_routine( void *arg )
{
int i;
int proc_num = (int)(long)arg;
cpu_set_t set;
CPU_ZERO( &set );
CPU_SET( proc_num, &set );
if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
{
perror( "sched_setaffinity" );
return NULL;
}
for (i = 0; i < INC_TO; i++)
{
global_int++;
// __sync_fetch_and_add( &global_int, 1 );
}
return NULL;
}
int main()
{
int procs = 0;
int i;
pthread_t *thrs;
// Getting number of CPUs
procs = (int)sysconf( _SC_NPROCESSORS_ONLN );
if (procs < 0)
{
perror( "sysconf" );
return -1;
}
thrs = malloc( sizeof( pthread_t ) * procs );
if (thrs == NULL)
{
perror( "malloc" );
return -1;
}
printf( "Starting %d threads... ", procs );
for (i = 0; i < procs; i++)
{
if (pthread_create( &thrs[i], NULL, thread_routine,
(void *)(long)i ))
{
perror( "pthread_create" );
procs = i;
break;
}
}
for (i = 0; i < procs; i++)
pthread_join( thrs[i], NULL );
free( thrs );
printf( "After doing all the math, global_int value is: %d ",
global_int );
printf( "Expected value is: %d ", INC_TO * procs );
return 0;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.