示例#1
0
文件: server.c 项目: grinya-mipt/MIPT
int main(int argc, char** argv){
	(void)umask(0);
//checking number of arguments and converting it (char*) to (int)
	if(argc != 2){
		printf("Invalid argument. Number of clients = %s\n",argv[1]);
		exit(-1);
	}
 	int n = atoi(argv[1]);
	if(n <= 0 || n == INT_MAX) print_err("invalid number of clients");

//create or get message quewe
	key_t msg_key = ftok(IPC_FTOK_FILE, 1);
	if(msg_key < 0) print_err("generation of IPC key");
	int msgid = msgget(msg_key, 0666 | IPC_CREAT);
	if(msgid < 0) print_err("create or get message quewe for sendind");

//Messege quewe info for debagging
	struct msginfo msg_data;
	if(msgctl(msgid, MSG_INFO, (struct msqid_ds*)&msg_data) < 0) print_err("get message quewe limits data");
	printf("Max message lenght = %d\nMax quewe lenght = %d\nMax number of quewes = %d\n", msg_data.msgmax, msg_data.msgmnb, msg_data.msgmni);

//open data file (format - from "generate" program)
	int fd;
	if((fd = open(DATA, O_RDONLY, 0666)) < 0) print_err("open data file");

//read matrixes from file
	int *mtx1,*mtx2;
	int mtx_sizes[3];
	read_matrixes(mtx_sizes, &mtx1, &mtx2, fd);
	if(close(fd) < 0) print_err("close data file");

//create supporting variables
	int i,j,tmp;

//create result matrix
	int* res = (int*)malloc(mtx_sizes[0]*mtx_sizes[0]*sizeof(int));

//defining work for different threads
	struct thread_data* thread;
	thread = (struct thread_data*)malloc((n+1)*sizeof(struct thread_data));
	int total_size_of_work = mtx_sizes[0]*mtx_sizes[2];

	if(total_size_of_work > n){
	//setting up number of elements (work_size) for calculation for each thread (case n < total_size_of_work)
		int initial_work = (mtx_sizes[0]*mtx_sizes[2])/n;
		int rest_work = (mtx_sizes[0]*mtx_sizes[2])%n;		
		for(i=0;i<n;i++) thread[i].work_size = initial_work;
		for(i=0;rest_work>0;rest_work--) ++thread[i++].work_size;
	//setting up coordinates of start point for each thread (case n < total_size_of_work)
		thread[0].i_start_index = thread[0].j_start_index = 0;
		for(i=1;i<n;i++) {
			thread[i].j_start_index = thread[i-1].j_start_index + thread[i-1].work_size/mtx_sizes[0];
			if( (thread[i].i_start_index = thread[i-1].i_start_index + thread[i-1].work_size%mtx_sizes[0]) >= mtx_sizes[0]){
				thread[i].j_start_index++;
				thread[i].i_start_index = thread[i-1].work_size%mtx_sizes[0] - mtx_sizes[0] + thread[i-1].i_start_index;
			}
		}
	//calculating usage of colomns and rows for each thread
		thread[n].i_start_index = 0;
		thread[n].j_start_index = mtx_sizes[2]; //here is a trick: we consider imaginary element with (i,j) = (0,mtx_size[2]) for short code
		for(i=0;i<n;i++){
			thread[i].col_count = (thread[i+1].i_start_index == 0) ? thread[i+1].j_start_index - thread[i].j_start_index : thread[i+1].j_start_index - thread[i].j_start_index + 1;
			if(thread[i].col_count == 1) thread[i].row_count = thread[i+1].i_start_index - thread[i].i_start_index;
			else if(thread[i].col_count == 2) thread[i].row_count = (thread[i+1].i_start_index >= thread[i].i_start_index) ? mtx_sizes[0] : mtx_sizes[0] + thread[i+1].i_start_index - thread[i+1].i_start_index; 
				else thread[i].row_count = mtx_sizes[0];
		}
	} else {
	//setting up numbers of elements for calculation and respective coordinates for each thread (case n >= total_size_of_work)
		thread[0].i_start_index = thread[0].j_start_index = 0;
		thread[0].work_size = thread[0].col_count = thread[0].row_count = 1;	
		for(i=1;i<total_size_of_work;i++){
			thread[i].work_size = 1;
			thread[i].col_count = 1;
			thread[i].row_count = 1;
			thread[i].i_start_index = (thread[i-1].i_start_index == (mtx_sizes[0] - 1) ) ? 0 : thread[i-1].i_start_index + 1;
			thread[i].j_start_index = (thread[i].i_start_index == 0) ? thread[i-1].j_start_index + 1 : thread[i-1].j_start_index;
		}
		for(i=total_size_of_work;i<n;i++) thread[i].work_size = 0;	
	}

//debugging information
	for(i = 0; i < n; i++) 
		printf("%d %d %d %d %d\n", thread[i].work_size, thread[i].row_count, thread[i].col_count, thread[i].i_start_index, thread[i].j_start_index);
		
//start timer
	struct timeval start_time;
	gettimeofday(&start_time, NULL);

//create and start threads for clients
	pthread_t *thread_id;
	thread_id = (pthread_t*)malloc(n*sizeof(pthread_t));
	for(i = 0; i < n; i++){
		thread[i].msgid = msgid;
		thread[i].mtx1 = mtx1;
		thread[i].mtx2 = mtx2;
		thread[i].res = res;
		thread[i].mtx_sizes[0] = mtx_sizes[0];
		thread[i].mtx_sizes[1] = mtx_sizes[1];
		thread[i].mtx_sizes[2] = mtx_sizes[2];		
		if(pthread_create(&thread_id[i], NULL, client, &thread[i]) > 0) print_err("create thread");
	}

//waiting for threads
	for(i = 0;i < n;i++) pthread_join(thread_id[i], (void**)NULL);

//free used heap
	free(mtx1);
	free(mtx2);
	free(thread);
	free(thread_id);

//print time of calculation
	struct timeval end_time;
	gettimeofday(&end_time,NULL);
	int delta = end_time.tv_usec - start_time.tv_usec;
	int sec = delta / (1000 * 1000);
	int msec = (delta - sec * 1000 * 1000) / 1000;
	int usec = delta - sec * 1000 * 1000 - msec * 1000;
	printf("Working time: %ds %dms %dmcs\n", sec, msec, usec);

//synchronization of clients' shutting down
	struct client_msg msg_s;
	struct client_msg msg_r;
	for(i=0;i<n;i++){
		msg_r.mtype = BYE_MSG_ID;
		if(msgrcv(msgid, (void*) &msg_r, sizeof(int),BYE_MSG_ID,0)<0) print_err("recieve BYE message from client");
		msg_s.mtype = msg_r.data[0];
		msg_s.data[0] = (i == n-1) ? 0 : 1;
		if(msgsnd(msgid, (void*) &msg_s, sizeof(int), 0) < 0) print_err("send BYE from server messege");	
	}

//delete message quewe
	if(msgrcv(msgid, (void*) &msg_r, 0, msg_r.data[0], 0)<0) print_err("recieve BYE message from last client");	

	if(msgctl(msgid, IPC_RMID, NULL) < 0) print_err("delete message quewe");

//write integer matrix into RES
	if ((fd = open(RES, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) print_err("open result file");
	char* buffer;
	char space = ' ', end = '\n';
	for(i = 0;i < mtx_sizes[0];i++) {
		for(j = 0;j < mtx_sizes[2];j++) {
			buffer = itoa(*(res + i*mtx_sizes[1] + j));
			write_into_file(fd,buffer,strlen(buffer));
			write_into_file(fd,&space,1);
			free(buffer);				
		}
		write_into_file(fd,&end,1);
	}
	free(res);	
	if(close(fd)) print_err("close result file");
	return 0;
}
示例#2
0
unsigned short dump_log::_write_thread_handler_internal()
{
#ifdef LOG_DEBUG
	printf("The worker thread of writing log is working\n");
#endif

	timespec tm_interval;
	int delay = 15;
	int res;
	while (!can_exit)
	{
		res = DUMP_LOG_SUCCESS;
        clock_gettime(CLOCK_REALTIME, &tm_interval);
        tm_interval.tv_sec += delay;
/*
The pthread_cond_timedwait() function blocks the calling thread, waiting for the condition specified by cond to be signaled or broadcast to.
When pthread_cond_timedwait() is called, the calling thread must have mutex locked.
The pthread_cond_timedwait() function atomically unlocks the mutex and performs the wait for the condition.
In this case, atomically means with respect to the mutex and the condition variable and other access by threads to those objects through the pthread condition variable interfaces.
Go to http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Fapis%2Fusers_77.htm for detailed info and example.
 */
        pthread_mutex_lock(&mtx_write);
        res = pthread_cond_timedwait(&cond_write, &mtx_write, &tm_interval);
        pthread_mutex_unlock(&mtx_write);
// No data to be written into the log file
        if(res == ETIMEDOUT)
        	continue;

        if(res != 0)
        {
           assert(0 && "Error occurs in timer thread");
           break;
        }

		if (write_event_list_head == NULL)
		{
// The buffer is empty
			write_event_list_head = add_event_list_head;
		}
		else
		{
// The buffer is NOT empty
			write_event_list_tail->item_next = add_event_list_head;
			add_event_list_head->item_prev = write_event_list_tail;
		}
		write_event_list_tail = add_event_list_tail;
		add_event_list_tail = add_event_list_head = NULL;

// Write the data into the log file
		res = write_into_file();
        if(res != DUMP_LOG_SUCCESS)
        {
           assert(0 && "Error occurs in timer thread");
           break;
        }
	}

	if (add_event_list_head != NULL)
	{
// Write the new events added in the list before the thread died
		write_event_list_head = add_event_list_head;
// Write the data left in the list into the log file
		res = write_into_file();
		if(res != DUMP_LOG_SUCCESS)
			assert(0 && "Error occurs in timer thread before leaving");
	}

#ifdef LOG_DEBUG
	printf("The worker thread of writing log is dead\n");
#endif
	return res;
}