1. /* Compile, for example: gcc pthread_example.c -lpthread -o pthread_example */ #include #include /* variable sum is shared by the threads */ int sum; /* thread */ void *runner(void *param); /* First thread */ main(int argc, char *argv[]) { /* Thread identifier */ pthread_t tid; /* Attributes for a thread (stack size, scheduling ...) */ pthread_attr_t attr; if (argc !=2){ fprintf(stderr,"Usage: %s \n",argv[0] ); exit(); } if (atoi(argv[1]) < 0) { fprintf(stderr,"(%d) must be >= 0\n",atoi(argv[1])); exit(); } /* Set attributes (default attributes are used) */ pthread_attr_init(&attr); /* Create a separate thread */ /* Pass a thread identifier (tid), attributes (attr), name of the */ /* function where the new thread will begin execution (runner), */ /* and the integer parameter provided on the command line (argv[1]) */ /* Now program has two threads: main and runner */ pthread_create(&tid,&attr,runner,argv[1]); /* main waits runner thread using pthread_join */ pthread_join(tid,NULL); /* print results of summing */ printf("Sum = %d\n",sum); } /* Second thread */ void *runner(void *param) { int upper = atoi(param); int i; sum = 0; if (upper > 0) { for (i=1; i<=upper; i++) sum +=i; } /* runner thread completes here */ pthread_exit(0); } Exercise 7: Task 2: Solution ---------------- Algorithm 3: Structure for process P_i do { flag[i] = true; turn = j; while (flag[j] && turn ==j); CRITICAL SECTION flag[i] = false; REMAINDER SECTION }while(1); MUTUAL EXCLUSION ================ critical section = CS 1) P_i enters its CS only if either flag[j] is false or turn is i 2) if both processes P_i and P_j can be executing in their CSs at the same time, then flag[0] is flag [1] is true Observations 1) and 2) imply that P_0 and P_1 could not have succesfully executed their while-statements at about the same time, since the following holds for turn: turn is 0 or turn is 1 but cannot be both (turn is 0 and turn is 1) One of the processes, say P_j, must have succesfully executed while statement (and at that time it cannot change the value of turn), whereas P_i had to execute at least one additional statement turn = j. At that time: flag[j] is true and turn is j and this will hold as long as P_j is in its CS. (and after executing in CS, P_j will set flag[j] = false, and P_i can enter its CS.) ==> Mutual exclusion is preserved. PROGRESS ======== * P_i can be prevented from executiong the CS ONLY if it is stuck in the while-loop with flag[j] is true and turn is j * If P_j is not ready to enter CS, then flag[j] is false and P_i can enter its CS. * If P_j has flag[j] is true and it is also executing in its while-loop, then either turn is i or turn is j ==> If turn == i, then P_i will enter its CS If turn == j, then P_j will enter its CS However, once P_j exits its CS, it sets flag[j] = false allowing P_i to enter its CS. If P_j resets flag[j] = true then it must also set turn = i. Thus, since P_i does not change the value of the variable turn when executing a while-loop, P_i will enter the CS after P_j. ==> Progress is preserved. BOUNDED WAITING =============== P_i will enter the CS after at most one CS execution by P_j ==> Bounded waiting is preserved. Mutual exclusion, progress, and bounded waiting are preserved ==> Algorithm 3 solves the critical section problem. 3. /* Compile: gcc socket_client.c -lnsl -lsocket -o socket_client */ /* Usage: for example, socket_client cs 6500 Hello */ /* socket_client 193.167.42.127 6500 "Hello again" */ #include #include #include #include #include main(argc,argv) int argc; char **argv; { int sock,len,N; struct sockaddr_in server; struct hostent *hp, *gethostbyname(); char buff[1024]; if (argc != 4) { fprintf(stderr,"usage: %s host port data\n",argv[0]); exit(1); } /* Create a socket */ /* AF_INET = address family Internet domain */ /* SOCK_STREAM = communication semantics */ /* Protocols, see /etc/protocols */ sock=socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("opening socket"); exit(1);} /* Find the IP-address for a name */ /* gethostbyname returns a structure of tyoe hostent for a given hostname */ /* See netdb.h or man gethostbyname for a definition on a structure */ /* hp contains a structure */ hp = gethostbyname(argv[1]); if (hp == 0) { fprintf(stderr,"unknown host [%s]\n",argv[1]); exit(1); } /* Set address family, IP-address, and a port number to structure */ /* sockaddr_in (server) */ /* bcopy copies the first n bytes of the source string src to the */ /* destination string dest. */ /* void bcopy (const void *src, void *dest, size_t n); */ bcopy((char *)hp->h_addr, (char *) &server.sin_addr, hp->h_length); /* set domain */ server.sin_family=AF_INET; /* Next change the order of bytes to order of network standard */ /* The htons() function converts the short integer hostshort */ /* from host byte order to network byte order. */ if (atoi(argv[2]) != 0) server.sin_port = htons(atoi(argv[2])); else /* default port */ server.sin_port = htons(6500); /* Send a request to a server */ if (connect(sock,(struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) { perror("sending"); exit(1); } /* Now connection is open. Now you can write to socket as writing to a file*/ N=strlen(argv[3]); if (write(sock,argv[3],N+1) != N+1) { perror("sending"); exit(1); } /* Close connection (socket) */ close(sock); exit(0); } /* gcc socket_server.c -lnsl -lsocket -o socket_server */ #include #include #include #include main(argc,argv) int argc; char **argv; { int sock,fd,len,n; struct sockaddr_in server; char buff[1024]; /* Create a socket */ sock=socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("opening socket"); exit(1);} /* Set server address family */ server.sin_family=AF_INET; /* Set the requesting client's address to INADDRR_ANY, no limitations */ server.sin_addr.s_addr=INADDR_ANY; /* Port 6500 */ server.sin_port=ntohs(6500); len = sizeof(server); /* bind a server to a socket */ if (bind(sock,(struct sockaddr *) &server, len) < 0) { perror("binding"); exit(1); } /* If systems decides the ports to be used then getsockname can be used */ if (getsockname(sock,(struct sockaddr *) &server, &len) < 0) { perror("getting name"); exit(1); } /* Print port number and tell it to a client */ /* ntohs() function converts the short integer netshort */ /* from network byte order to host byte order. */ printf("Client can send now the data to port #%d\n", ntohs(server.sin_port)); /* Start listening a socket, create a queue of 5 requests */ listen(sock,5); do{ /* Accept a request, and create socket for it */ fd=accept(sock,(struct sockaddr *)0,(int *)0); if (fd == -1) {perror("accept fd");exit(1);} else do { /* read a socket, n is number of bytes succesfully read */ n=read(fd,buff,1024); if (n < 0) perror("read socket"); else if (n==0) printf("EOF received.\n"); else printf("> %s\n",buff); }while(n > 0); /* close a socket and wait for a new request */ close(fd); }while(1); }