⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sync0arr.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************The wait array used in synchronization primitives(c) 1995 Innobase OyCreated 9/5/1995 Heikki Tuuri*******************************************************/#include "sync0arr.h"#ifdef UNIV_NONINL#include "sync0arr.ic"#endif#include "sync0sync.h"#include "sync0rw.h"#include "os0sync.h"#include "os0file.h"#include "srv0srv.h"/*			WAIT ARRAY			==========The wait array consists of cells each of which has anan operating system event object created for it. The threadswaiting for a mutex, for example, can reserve a cellin the array and suspend themselves to wait for the eventto become signaled. When using the wait array, remember to makesure that some thread holding the synchronization objectwill eventually know that there is a waiter in the array andsignal the object, to prevent infinite wait.Why we chose to implement a wait array? First, to makemutexes fast, we had to code our own implementation of them,which only in usually uncommon cases resorts to usingslow operating system primitives. Then we had the choice ofassigning a unique OS event for each mutex, which wouldbe simpler, or using a global wait array. In some operating systems,the global wait array solution is more efficient and flexible,because we can do with a very small number of OS events,say 200. In NT 3.51, allocating events seems to be a quadraticalgorithm, because 10 000 events are created fast, but100 000 events takes a couple of minutes to create.*//* A cell where an individual thread may wait suspendeduntil a resource is released. The suspending is implementedusing an operating system event semaphore. */struct sync_cell_struct {        void*           wait_object;    /* pointer to the object the                                        thread is waiting for; if NULL                                        the cell is free for use */	mutex_t*	old_wait_mutex;	/* the latest wait mutex in cell */	rw_lock_t*	old_wait_rw_lock;/* the latest wait rw-lock in cell */        ulint		request_type;	/* lock type requested on the        				object */	const char*	file;		/* in debug version file where					requested */	ulint		line;		/* in debug version line where					requested */	os_thread_id_t	thread;		/* thread id of this waiting					thread */	ibool		waiting;	/* TRUE if the thread has already					called sync_array_event_wait					on this cell */	ibool		event_set;	/* TRUE if the event is set */        os_event_t 	event;   	/* operating system event                                        semaphore handle */	time_t		reservation_time;/* time when the thread reserved					the wait cell */};/* NOTE: It is allowed for a thread to waitfor an event allocated for the array without owning theprotecting mutex (depending on the case: OS or database mutex), butall changes (set or reset) to the state of the event must be madewhile owning the mutex. */struct sync_array_struct {	ulint		n_reserved;	/* number of currently reserved					cells in the wait array */	ulint		n_cells;	/* number of cells in the					wait array */	sync_cell_t*	array;		/* pointer to wait array */	ulint		protection;	/* this flag tells which					mutex protects the data */	mutex_t		mutex;		/* possible database mutex					protecting this data structure */	os_mutex_t	os_mutex;	/* Possible operating system mutex					protecting the data structure.					As this data structure is used in					constructing the database mutex,					to prevent infinite recursion					in implementation, we fall back to					an OS mutex. */	ulint		sg_count;	/* count of how many times an					object has been signalled */	ulint		res_count;	/* count of cell reservations					since creation of the array */};#ifdef UNIV_SYNC_DEBUG/**********************************************************************This function is called only in the debug version. Detects a deadlockof one or more threads because of waits of semaphores. */staticiboolsync_array_detect_deadlock(/*=======================*/				/* out: TRUE if deadlock detected */        sync_array_t*	arr,	/* in: wait array; NOTE! the caller must        			own the mutex to array */	sync_cell_t*	start,	/* in: cell where recursive search started */	sync_cell_t*	cell,	/* in: cell to search */	ulint		depth);	/* in: recursion depth */#endif /* UNIV_SYNC_DEBUG *//*********************************************************************Gets the nth cell in array. */staticsync_cell_t*sync_array_get_nth_cell(/*====================*/				/* out: cell */	sync_array_t*	arr,	/* in: sync array */	ulint		n)	/* in: index */{	ut_a(arr);	ut_a(n < arr->n_cells);	return(arr->array + n);}/**********************************************************************Reserves the mutex semaphore protecting a sync array. */staticvoidsync_array_enter(/*=============*/	sync_array_t*	arr)	/* in: sync wait array */{	ulint	protection;	protection = arr->protection;	if (protection == SYNC_ARRAY_OS_MUTEX) {		os_mutex_enter(arr->os_mutex);	} else if (protection == SYNC_ARRAY_MUTEX) {		mutex_enter(&(arr->mutex));	} else {		ut_error;	}}/**********************************************************************Releases the mutex semaphore protecting a sync array. */staticvoidsync_array_exit(/*============*/	sync_array_t*	arr)	/* in: sync wait array */{	ulint	protection;	protection = arr->protection;	if (protection == SYNC_ARRAY_OS_MUTEX) {		os_mutex_exit(arr->os_mutex);	} else if (protection == SYNC_ARRAY_MUTEX) {		mutex_exit(&(arr->mutex));	} else {		ut_error;	}}/***********************************************************************Creates a synchronization wait array. It is protected by a mutexwhich is automatically reserved when the functions operating on itare called. */sync_array_t*sync_array_create(/*==============*/				/* out, own: created wait array */	ulint	n_cells,	/* in: number of cells in the array				to create */	ulint	protection)	/* in: either SYNC_ARRAY_OS_MUTEX or				SYNC_ARRAY_MUTEX: determines the type				of mutex protecting the data structure */{	sync_array_t*	arr;	sync_cell_t*	cell_array;	sync_cell_t*	cell;	ulint		i;		ut_a(n_cells > 0);	/* Allocate memory for the data structures */	arr = ut_malloc(sizeof(sync_array_t));	cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells);	arr->n_cells = n_cells;	arr->n_reserved = 0;	arr->array = cell_array;	arr->protection = protection;	arr->sg_count = 0;	arr->res_count = 0;        /* Then create the mutex to protect the wait array complex */	if (protection == SYNC_ARRAY_OS_MUTEX) {		arr->os_mutex = os_mutex_create(NULL);	} else if (protection == SYNC_ARRAY_MUTEX) {		mutex_create(&(arr->mutex));		mutex_set_level(&(arr->mutex), SYNC_NO_ORDER_CHECK);	} else {		ut_error;	}        for (i = 0; i < n_cells; i++) {		cell = sync_array_get_nth_cell(arr, i);        	                cell->wait_object = NULL;                /* Create an operating system event semaphore with no name */                cell->event = os_event_create(NULL);		cell->event_set = FALSE; /* it is created in reset state */	}	return(arr);}/**********************************************************************Frees the resources in a wait array. */voidsync_array_free(/*============*/	sync_array_t*	arr)	/* in, own: sync wait array */{        ulint           i;        sync_cell_t*   	cell;	ulint		protection;        ut_a(arr->n_reserved == 0);        	sync_array_validate(arr);                for (i = 0; i < arr->n_cells; i++) {		cell = sync_array_get_nth_cell(arr, i);        			os_event_free(cell->event);        }	protection = arr->protection;        /* Release the mutex protecting the wait array complex */	if (protection == SYNC_ARRAY_OS_MUTEX) {		os_mutex_free(arr->os_mutex);	} else if (protection == SYNC_ARRAY_MUTEX) {		mutex_free(&(arr->mutex));	} else {		ut_error;	}	ut_free(arr->array);	ut_free(arr);	}/************************************************************************Validates the integrity of the wait array. Checksthat the number of reserved cells equals the count variable. */voidsync_array_validate(/*================*/	sync_array_t*	arr)	/* in: sync wait array */{        ulint           i;        sync_cell_t*   	cell;        ulint           count           = 0;                sync_array_enter(arr);        for (i = 0; i < arr->n_cells; i++) {		cell = sync_array_get_nth_cell(arr, i);        	                if (cell->wait_object != NULL) {                        count++;                }        }        ut_a(count == arr->n_reserved);        sync_array_exit(arr);}/***********************************************************************Puts the cell event in set state. */staticvoidsync_cell_event_set(/*================*/	sync_cell_t*	cell)	/* in: array cell */{	os_event_set(cell->event);	cell->event_set = TRUE;}		/***********************************************************************Puts the cell event in reset state. */staticvoidsync_cell_event_reset(/*==================*/	sync_cell_t*	cell)	/* in: array cell */{	os_event_reset(cell->event);	cell->event_set = FALSE;}		/**********************************************************************Reserves a wait array cell for waiting for an object.The event of the cell is reset to nonsignalled state. */voidsync_array_reserve_cell(/*====================*/        sync_array_t*	arr,	/* in: wait array */        void*   	object, /* in: pointer to the object to wait for */        ulint		type,	/* in: lock request type */	const char*	file,	/* in: file where requested */        ulint		line,	/* in: line where requested */        ulint*   	index)  /* out: index of the reserved cell */{        sync_cell_t*   	cell;        ulint           i;                ut_a(object);        ut_a(index);        sync_array_enter(arr);        arr->res_count++;	/* Reserve a new cell. */        for (i = 0; i < arr->n_cells; i++) {		cell = sync_array_get_nth_cell(arr, i);        	                if (cell->wait_object == NULL) {                        /* Make sure the event is reset */			if (cell->event_set) {	                        	sync_cell_event_reset(cell);			}			cell->reservation_time = time(NULL);			cell->thread = os_thread_get_curr_id();			cell->wait_object = object;			if (type == SYNC_MUTEX) {				cell->old_wait_mutex = object;			} else {				cell->old_wait_rw_lock = object;			}							cell->request_type = type;			cell->waiting = FALSE;						cell->file = file;			cell->line = line;						arr->n_reserved++;			*index = i;			sync_array_exit(arr);                                                return;                }        }        ut_error; /* No free cell found */	return;}/**********************************************************************This function should be called when a thread starts to wait ona wait array cell. In the debug version this function checksif the wait for a semaphore will result in a deadlock, in whichcase prints info and asserts. */voidsync_array_wait_event(/*==================*/        sync_array_t*	arr,	/* in: wait array */        ulint   	index)  /* in: index of the reserved cell */{        sync_cell_t*   	cell;        os_event_t 	event;                ut_a(arr);        sync_array_enter(arr);	cell = sync_array_get_nth_cell(arr, index);        		ut_a(cell->wait_object);	ut_a(!cell->waiting);	ut_ad(os_thread_get_curr_id() == cell->thread);       	event = cell->event;       	cell->waiting = TRUE;#ifdef UNIV_SYNC_DEBUG       		/* We use simple enter to the mutex below, because if	we cannot acquire it at once, mutex_enter would call	recursively sync_array routines, leading to trouble.	rw_lock_debug_mutex freezes the debug lists. */	rw_lock_debug_mutex_enter();	if (TRUE == sync_array_detect_deadlock(arr, cell, cell, 0)) {		fputs("########################################\n", stderr);		ut_error;	}			rw_lock_debug_mutex_exit();#endif        sync_array_exit(arr);        os_event_wait(event);        sync_array_free_cell(arr, index);}/**********************************************************************Reports info of a wait array cell. */staticvoidsync_array_cell_print(/*==================*/	FILE*		file,	/* in: file where to print */	sync_cell_t*	cell)	/* in: sync cell */{	mutex_t*	mutex;	rw_lock_t*	rwlock;	ulint		type;	type = cell->request_type;	fprintf(file,"--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n",			(ulong) os_thread_pf(cell->thread), cell->file,		       (ulong) cell->line,		       difftime(time(NULL), cell->reservation_time));	if (type == SYNC_MUTEX) {		/* We use old_wait_mutex in case the cell has already		been freed meanwhile */		mutex = cell->old_wait_mutex;		fprintf(file,			"Mutex at %p created file %s line %lu, lock var %lu\n"#ifdef UNIV_SYNC_DEBUG			"Last time reserved in file %s line %lu, "#endif /* UNIV_SYNC_DEBUG */			"waiters flag %lu\n",			mutex, mutex->cfile_name, (ulong) mutex->cline,			(ulong) mutex->lock_word,#ifdef UNIV_SYNC_DEBUG			mutex->file_name, (ulong) mutex->line,#endif /* UNIV_SYNC_DEBUG */			(ulong) mutex->waiters);	} else if (type == RW_LOCK_EX || type == RW_LOCK_SHARED) {		fputs(type == RW_LOCK_EX ? "X-lock on" : "S-lock on", file);		rwlock = cell->old_wait_rw_lock;		fprintf(file,			" RW-latch at %p created in file %s line %lu\n",			rwlock, rwlock->cfile_name,			(ulong) rwlock->cline);		if (rwlock->writer != RW_LOCK_NOT_LOCKED) {			fprintf(file,			"a writer (thread id %lu) has reserved it in mode %s",				(ulong) os_thread_pf(rwlock->writer_thread),				rwlock->writer == RW_LOCK_EX				? " exclusive\n"				: " wait exclusive\n");		}				fprintf(file,			"number of readers %lu, waiters flag %lu\n"			"Last time read locked in file %s line %lu\n"			"Last time write locked in file %s line %lu\n",			(ulong) rwlock->reader_count,			(ulong) rwlock->waiters,			rwlock->last_s_file_name,			(ulong) rwlock->last_s_line,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -