diff options
Diffstat (limited to 'innobase/com/com0shm.c')
-rw-r--r-- | innobase/com/com0shm.c | 1130 |
1 files changed, 0 insertions, 1130 deletions
diff --git a/innobase/com/com0shm.c b/innobase/com/com0shm.c deleted file mode 100644 index 09876e6e8b5..00000000000 --- a/innobase/com/com0shm.c +++ /dev/null @@ -1,1130 +0,0 @@ -/****************************************************** -The communication through shared memory - -(c) 1995 Innobase Oy - -Created 9/25/1995 Heikki Tuuri -*******************************************************/ - -#include "com0shm.h" -#ifdef UNIV_NONINL -#include "com0shm.ic" -#endif - -#include "mem0mem.h" -#include "ut0mem.h" -#include "com0com.h" -#include "os0shm.h" -#include "sync0sync.h" -#include "sync0ipm.h" -#include "hash0hash.h" - -/* - IMPLEMENTATION OF COMMUNICATION PRIMITIVES - ========================================== - -When bind is called for an endpoint, a shared memory area of -a size specified by com_shm_set_option is created with the -name of the address given concatenated to "_IBSHM". -Also a mutex is created for controlling the access to the -shared memory area. The name of the mutex is address + "_IBSHM_MTX". -An event with name address + "_IBSHM_EV_NE" is created. This event -is in signaled state when the shared memory area is not empty, i.e., -there is a datagram to read. An event address + "_IBSHM_EV_EM" -is signaled, when the area is empty, i.e., a datagram can be -written to it. - -The shared memory area consists of an info struct -at the beginning, containing fields telling: -if the area is valid, i.e., is anybody going to -read it, whether it currently contains a datagram, the -length of the address from which the datagram was received, -the length of the datagram, and the maximum allowed length of -a datagram. -After the info struct, there is a string of bytes -containing the sender address and the data -of the datagram. -*/ - -/* The following is set TRUE when the first endpoint is created. */ - -ibool com_shm_initialized = FALSE; - -/* When a datagram is sent, the shared memory area -corresponding to the destination address is mapped -to the address space of this (sender) process. -We preserve it and keep the relevant info in the -following list. We can save a lot of CPU time -if the destination can be found on the list. The list is -protected by the mutex below. */ - -mutex_t com_shm_destination_mutex; -hash_table_t* com_shm_destination_cache; -UT_LIST_BASE_NODE_T(com_shm_endpoint_t) - com_shm_destination_list; - -/* The number of successfully bound endpoints in this process. When this -number drops to 0, the destination cache is freed. This variable is protected -by com_shm_destination_mutex above. */ - -ulint com_shm_bind_count = 0; - -/* The performance of communication in NT depends on how -many times a system call is made (excluding os_thread_yield, -as that is the fastest way to switch thread). -The following variable counts such events. */ - -ulint com_shm_system_call_count = 0; - -/* The info struct at the beginning of a shared memory area */ - -typedef struct com_shm_info_struct com_shm_info_t; - -/* An area of shared memory consists of an info struct followed -by a string of bytes. */ - -typedef com_shm_info_t com_shm_t; - -struct com_shm_endpoint_struct{ - ibool owns_shm; /* This is true if the shared memory - area is owned by this endpoint structure - (it may also be opened for this endpoint, - not created, in which case does not own it) */ - char* addr; /* pointer to address the endpoint is bound - to, NULL if not bound */ - ulint addr_len; /* address length */ - ulint size; /* maximum allowed datagram size, initialized - to 0 at creation */ - os_shm_t shm; /* operating system handle of the shared - memory area */ - com_shm_t* map; /* pointer to the start address of the shared - memory area */ - os_event_t not_empty; /* this is in the signaled state if - the area currently may contain a datagram; - NOTE: automatic event */ - os_event_t empty; /* this is in the signaled state if the area - currently may be empty; NOTE: automatic - event */ - ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex - protecting the shared memory */ - UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct - is inserted into a list, this contains - pointers to next and prev */ - com_shm_endpoint_t* addr_hash; - /* hash table link */ -}; - -struct com_shm_info_struct{ - ulint valid; /* This is COM_SHM_VALID if the creator - of the shared memory area has it still - mapped to its address space. Otherwise, - we may conclude that the datagram cannot - be delivered. */ - ibool not_empty; /* TRUE if the area currently contains - a datagram */ - ulint empty_waiters; /* Count of (writer) threads which are - waiting for the empty-event */ - ulint max_len;/* maximum allowed length for a datagram */ - ulint addr_len;/* address length for the sender address */ - ulint data_len;/* datagram length */ - ip_mutex_t ip_mutex;/* fast interprocess mutex protecting - the shared memory area */ -}; - -#define COM_SHM_VALID 76640 - -/************************************************************************* -Accessor functions for a shared memory endpoint */ - -UNIV_INLINE -ibool -com_shm_endpoint_get_owns_shm( -/*==========================*/ - com_shm_endpoint_t* ep) -{ - ut_ad(ep); - return(ep->owns_shm); -} - -UNIV_INLINE -void -com_shm_endpoint_set_owns_shm( -/*==========================*/ - com_shm_endpoint_t* ep, - ibool flag) -{ - ut_ad(ep); - - ep->owns_shm = flag; -} - -UNIV_INLINE -char* -com_shm_endpoint_get_addr( -/*======================*/ - com_shm_endpoint_t* ep) -{ - ut_ad(ep); - return(ep->addr); -} - -UNIV_INLINE -void -com_shm_endpoint_set_addr( -/*======================*/ - com_shm_endpoint_t* ep, - char* addr) -{ - ut_ad(ep); - - ep->addr = addr; -} - -UNIV_INLINE -ulint -com_shm_endpoint_get_addr_len( -/*==========================*/ - com_shm_endpoint_t* ep) -{ - return(ep->addr_len); -} - -UNIV_INLINE -void -com_shm_endpoint_set_addr_len( -/*==========================*/ - com_shm_endpoint_t* ep, - ulint len) -{ - ut_ad(ep); - ut_ad(len > 0); - - ep->addr_len = len; -} - -ulint -com_shm_endpoint_get_size( -/*======================*/ - com_shm_endpoint_t* ep) -{ - return(ep->size); -} - -UNIV_INLINE -void -com_shm_endpoint_set_size( -/*======================*/ - com_shm_endpoint_t* ep, - ulint size) -{ - ut_ad(ep); - - ep->size = size; -} - -UNIV_INLINE -os_shm_t -com_shm_endpoint_get_shm( -/*=====================*/ - com_shm_endpoint_t* ep) -{ - return(ep->shm); -} - -UNIV_INLINE -void -com_shm_endpoint_set_shm( -/*=====================*/ - com_shm_endpoint_t* ep, - os_shm_t shm) -{ - ut_ad(ep); - ut_ad(shm); - - ep->shm = shm; -} - -UNIV_INLINE -com_shm_t* -com_shm_endpoint_get_map( -/*=====================*/ - com_shm_endpoint_t* ep) -{ - return(ep->map); -} - -UNIV_INLINE -void -com_shm_endpoint_set_map( -/*=====================*/ - com_shm_endpoint_t* ep, - com_shm_t* map) -{ - ut_ad(ep); - ut_ad(map); - - ep->map = map; -} - -UNIV_INLINE -os_event_t -com_shm_endpoint_get_empty( -/*=======================*/ - com_shm_endpoint_t* ep) -{ - return(ep->empty); -} - -UNIV_INLINE -void -com_shm_endpoint_set_empty( -/*=======================*/ - com_shm_endpoint_t* ep, - os_event_t event) -{ - ut_ad(ep); - ut_ad(event); - - ep->empty = event; -} - -UNIV_INLINE -os_event_t -com_shm_endpoint_get_not_empty( -/*===========================*/ - com_shm_endpoint_t* ep) -{ - return(ep->not_empty); -} - -UNIV_INLINE -void -com_shm_endpoint_set_not_empty( -/*===========================*/ - com_shm_endpoint_t* ep, - os_event_t event) -{ - ut_ad(ep); - ut_ad(event); - - ep->not_empty = event; -} - -/************************************************************************ -Accessor functions for the shared memory area info struct. */ -UNIV_INLINE -ulint -com_shm_get_valid( -/*==============*/ - com_shm_info_t* info) -{ - return(info->valid); -} - -UNIV_INLINE -void -com_shm_set_valid( -/*==============*/ - com_shm_info_t* info, - ulint flag) -{ - ut_ad(info); - - info->valid = flag; -} - -UNIV_INLINE -ibool -com_shm_get_not_empty( -/*==================*/ - com_shm_info_t* info) -{ - return(info->not_empty); -} - -UNIV_INLINE -void -com_shm_set_not_empty( -/*==================*/ - com_shm_info_t* info, - ibool flag) -{ - ut_ad(info); - - info->not_empty = flag; -} - -UNIV_INLINE -ulint -com_shm_get_empty_waiters( -/*======================*/ - com_shm_info_t* info) -{ - ut_ad(info->empty_waiters < 1000); - - return(info->empty_waiters); -} - -UNIV_INLINE -void -com_shm_set_empty_waiters( -/*======================*/ - com_shm_info_t* info, - ulint count) -{ - ut_ad(info); - ut_ad(count < 1000); - - info->empty_waiters = count; -} - -UNIV_INLINE -ulint -com_shm_get_max_len( -/*================*/ - com_shm_info_t* info) -{ - return(info->max_len); -} - -UNIV_INLINE -void -com_shm_set_max_len( -/*================*/ - com_shm_info_t* info, - ulint len) -{ - ut_ad(info); - ut_ad(len > 0); - - info->max_len = len; -} - -UNIV_INLINE -ulint -com_shm_get_addr_len( -/*=================*/ - com_shm_info_t* info) -{ - return(info->addr_len); -} - -UNIV_INLINE -void -com_shm_set_addr_len( -/*=================*/ - com_shm_info_t* info, - ulint len) -{ - ut_ad(info); - ut_ad(len > 0); - - info->addr_len = len; -} - -UNIV_INLINE -ulint -com_shm_get_data_len( -/*=================*/ - com_shm_info_t* info) -{ - return(info->data_len); -} - -UNIV_INLINE -void -com_shm_set_data_len( -/*=================*/ - com_shm_info_t* info, - ulint len) -{ - ut_ad(info); - ut_ad(len > 0); - - info->data_len = len; -} - -UNIV_INLINE -ip_mutex_t* -com_shm_get_ip_mutex( -/*=================*/ - com_shm_info_t* info) -{ - return(&(info->ip_mutex)); -} - -/************************************************************************* -Accessor functions for the address and datagram fields inside a -shared memory area. */ - -UNIV_INLINE -char* -com_shm_get_addr( -/*=============*/ - com_shm_t* area) -{ - return((char*)area + sizeof(com_shm_info_t)); -} - -UNIV_INLINE -byte* -com_shm_get_data( -/*=============*/ - com_shm_t* area) -{ - return((byte*)com_shm_get_addr(area) + com_shm_get_addr_len(area)); -} - -/************************************************************************* -Initializes the shared memory communication system for this -process. */ -UNIV_INLINE -void -com_shm_init(void) -/*==============*/ -{ - mutex_create(&com_shm_destination_mutex); - - mutex_set_level(&com_shm_destination_mutex, SYNC_ANY_LATCH); - - com_shm_destination_cache = hash_create(1000); - - UT_LIST_INIT(com_shm_destination_list); - - com_shm_initialized = TRUE; -} - -/************************************************************************* -Reserves the ip mutex of the shared memory area of an endpoint. */ -UNIV_INLINE -void -com_shm_enter( -/*==========*/ - com_shm_endpoint_t* ep) -{ - ulint ret; - - ret = ip_mutex_enter(ep->ip_mutex, 10000000); - - if (ret != 0) { - mutex_list_print_info(); - - ut_error; - } -} - -/************************************************************************* -Releases the ip mutex of the shared memory area of an endpoint. */ -UNIV_INLINE -void -com_shm_exit( -/*=========*/ - com_shm_endpoint_t* ep) -{ - ip_mutex_exit(ep->ip_mutex); -} - -/************************************************************************* -Looks for the given address in the cached destination addresses. */ -UNIV_INLINE -com_shm_endpoint_t* -com_shm_destination_cache_search( -/*=============================*/ - /* out: cached endpoint structure if found, else NULL */ - char* addr, /* in: destination address */ - ulint len) /* in: address length */ -{ - com_shm_endpoint_t* ep; - ulint fold; - - fold = ut_fold_binary((byte*)addr, len); -/* - printf("Searching dest. cache %s %lu fold %lu\n", addr, len, fold); -*/ - mutex_enter(&com_shm_destination_mutex); - - HASH_SEARCH(addr_hash, com_shm_destination_cache, fold, ep, - ((ep->addr_len == len) - && (0 == ut_memcmp(addr, ep->addr, len)))); - - mutex_exit(&com_shm_destination_mutex); - - return(ep); -} - -/************************************************************************* -Inserts the given endpoint structure in the cached destination addresses. */ -static -void -com_shm_destination_cache_insert( -/*=============================*/ - com_shm_endpoint_t* ep) /* in: endpoint struct to insert */ -{ - ulint fold; - - fold = ut_fold_binary((byte*)(ep->addr), ep->addr_len); - - mutex_enter(&com_shm_destination_mutex); - - /* Add to hash table */ - HASH_INSERT(com_shm_endpoint_t, - addr_hash, com_shm_destination_cache, fold, ep); - - UT_LIST_ADD_LAST(list, com_shm_destination_list, ep); - -/* printf("Inserting to dest. cache %s %lu fold %lu\n", ep->addr, - ep->addr_len, fold); -*/ - mutex_exit(&com_shm_destination_mutex); -} - -/************************************************************************* -Frees the endpoint structs in the destination cache if the bind count is zero. -If it is not, some send operation may just be using a cached endpoint and it -cannot be freed. */ -static -void -com_shm_destination_cache_no_binds(void) -/*====================================*/ -{ - com_shm_endpoint_t* ep; - ulint fold; - - mutex_enter(&com_shm_destination_mutex); - - if (com_shm_bind_count != 0) { - mutex_exit(&com_shm_destination_mutex); - - return; - } - - while (UT_LIST_GET_LEN(com_shm_destination_list) != 0) { - - ep = UT_LIST_GET_FIRST(com_shm_destination_list); - - UT_LIST_REMOVE(list, com_shm_destination_list, ep); - - fold = ut_fold_binary((byte*)ep->addr, ep->addr_len); -/* - printf("Deleting from dest. cache %s %lu fold %lu\n", - ep->addr, - ep->addr_len, fold); -*/ - HASH_DELETE(com_shm_endpoint_t, addr_hash, - com_shm_destination_cache, fold, ep); - - com_shm_endpoint_free(ep); - } - - mutex_exit(&com_shm_destination_mutex); -} - -/*********************************************************************** -Unbinds an endpoint at the time of freeing. */ -static -void -com_shm_unbind( -/*===========*/ - com_shm_endpoint_t* ep) /* in: endpoint */ -{ - com_shm_t* map; - - map = com_shm_endpoint_get_map(ep); - - /* Mark the shared memory area invalid */ - - com_shm_set_valid(map, 0); - - /* Decrement the count of bindings */ - - mutex_enter(&com_shm_destination_mutex); - - com_shm_bind_count--; - - mutex_exit(&com_shm_destination_mutex); - - /* If there are no binds left, free the cached endpoints */ - - com_shm_destination_cache_no_binds(); -} - -/************************************************************************* -Creates a communications endpoint. */ - -com_shm_endpoint_t* -com_shm_endpoint_create(void) -/*=========================*/ - /* out, own: communications endpoint, NULL if - did not succeed */ -{ - com_shm_endpoint_t* ep; - - if (!com_shm_initialized) { - - com_shm_init(); - } - - ep = mem_alloc(sizeof(com_shm_endpoint_t)); - - com_shm_endpoint_set_owns_shm(ep, FALSE); - com_shm_endpoint_set_addr(ep, NULL); - com_shm_endpoint_set_size(ep, 0); - - return(ep); -} - -/************************************************************************* -Frees a communications endpoint. */ - -ulint -com_shm_endpoint_free( -/*==================*/ - /* out: O if succeed, else error number */ - com_shm_endpoint_t* ep) /* in, own: communications endpoint */ -{ - com_shm_t* map; - - ut_ad(ep); - - if (com_shm_endpoint_get_addr(ep) != NULL) { - - map = com_shm_endpoint_get_map(ep); - - if (com_shm_endpoint_get_owns_shm(ep)) { - - com_shm_unbind(ep); - } - - /* We do not destroy the data structures in the shared memory - area, because we cannot be sure that there is currently no - process accessing it. Therefore we just close the ip_mutex - residing in the area. */ - - ip_mutex_close(ep->ip_mutex); - - os_event_free(com_shm_endpoint_get_not_empty(ep)); - os_event_free(com_shm_endpoint_get_empty(ep)); - - os_shm_unmap(map); - os_shm_free(com_shm_endpoint_get_shm(ep)); - - mem_free(com_shm_endpoint_get_addr(ep)); - } - - mem_free(ep); - - return(0); -} - -/************************************************************************* -Sets an option, like the maximum datagram size for an endpoint. -The options may vary depending on the endpoint type. */ - -ulint -com_shm_endpoint_set_option( -/*========================*/ - /* out: 0 if succeed, else error number */ - com_shm_endpoint_t* ep, /* in: endpoint */ - ulint optno, /* in: option number, only - COM_OPT_MAX_DGRAM_SIZE currently supported */ - byte* optval, /* in: pointer to a buffer containing the - option value to set */ - ulint optlen) /* in: option value buffer length */ -{ - ulint size; - - UT_NOT_USED(optlen); - - ut_ad(ep); - ut_a(optno == COM_OPT_MAX_DGRAM_SIZE); - ut_ad(NULL == com_shm_endpoint_get_addr(ep)); - - size = *((ulint*)optval); - - ut_ad(size > 0); - - com_shm_endpoint_set_size(ep, size); - - return(0); -} - -/************************************************************************* -This function is used either to create a new shared memory area or open an -existing one, but this does not do the operations necessary with the ip mutex. -They are performed in com_shm_bind or com_shm_open which call this function. */ -static -ulint -com_shm_create_or_open( -/*===================*/ - /* out: 0 if succeed, else error number */ - com_shm_endpoint_t* ep, /* in: communications endpoint */ - char* name, /* in: address name */ - ulint len) /* in: address name length */ -{ - os_shm_t shm; - com_shm_t* map; - os_event_t event_ne; - os_event_t event_em; - char* buf; - - ut_ad(ep); - ut_ad(name); - ut_ad(len > 0); - - buf = mem_alloc(COM_MAX_ADDR_LEN + 20); - - ut_memcpy(buf, name, len); - - ut_strcpy(buf + len, (char*)"_IBSHM"); - - shm = os_shm_create(sizeof(com_shm_info_t) + COM_MAX_ADDR_LEN + - com_shm_endpoint_get_size(ep), buf); - if (shm == NULL) { - - return(COM_ERR_NOT_SPECIFIED); - } - - map = os_shm_map(shm); - - if (map == NULL) { - os_shm_free(shm); - - return(COM_ERR_NOT_SPECIFIED); - } - - ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"), - - event_ne = os_event_create(buf); - - ut_ad(event_ne); - - ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"), - - event_em = os_event_create(buf); - - ut_ad(event_em); - - ut_a(0); /* event_ne and event_em should be auto events! */ - - com_shm_endpoint_set_shm(ep, shm); - com_shm_endpoint_set_map(ep, map); - - com_shm_endpoint_set_not_empty(ep, event_ne); - com_shm_endpoint_set_empty(ep, event_em); - - com_shm_endpoint_set_addr(ep, buf); - com_shm_endpoint_set_addr_len(ep, len); - - return(0); -} - -/************************************************************************* -Opens a shared memory area for communication. */ -static -ulint -com_shm_open( -/*=========*/ - /* out: 0 if succeed, else error number */ - com_shm_endpoint_t* ep, /* in: communications endpoint */ - char* name, /* in: address name */ - ulint len) /* in: address name length */ -{ - ip_mutex_hdl_t* ip_hdl; - com_shm_t* map; - ulint ret; - char buf[COM_MAX_ADDR_LEN + 20]; - - ret = com_shm_create_or_open(ep, name, len); - - if (ret != 0) { - - return(ret); - } - - map = com_shm_endpoint_get_map(ep); - - /* Open the interprocess mutex to protect the shared memory area */ - - ut_memcpy(buf, name, len); - ut_strcpy(buf + len, (char*)"_IBSHM_MTX"); - - ret = ip_mutex_open(com_shm_get_ip_mutex(map), buf, &ip_hdl); - - if (ret != 0) { - - return(COM_ERR_NOT_SPECIFIED); - } - - ep->ip_mutex = ip_hdl; - - return(0); -} - -/************************************************************************* -Creates a shared memory area for communication. */ - -ulint -com_shm_bind( -/*=========*/ - /* out: 0 if succeed, else error number */ - com_shm_endpoint_t* ep, /* in: communications endpoint */ - char* name, /* in: address name */ - ulint len) /* in: address name length */ -{ - com_shm_t* map; - ulint ret; - char buf[COM_MAX_ADDR_LEN + 20]; - ip_mutex_hdl_t* ip_hdl; - - if (com_shm_endpoint_get_size(ep) == 0) { - - return(COM_ERR_MAX_DATAGRAM_SIZE_NOT_SET); - } - - ret = com_shm_create_or_open(ep, name, len); - - if (ret != 0) { - - return(ret); - } - - map = com_shm_endpoint_get_map(ep); - - /* Create the interprocess mutex to protect the shared memory area */ - - ut_memcpy(buf, name, len); - ut_strcpy(buf + len, (char*)"_IBSHM_MTX"); - - ret = ip_mutex_create(com_shm_get_ip_mutex(map), buf, &ip_hdl); - - if (ret != 0) { - - return(COM_ERR_NOT_SPECIFIED); - } - - /* This endpoint structure owns the shared memory area */ - - com_shm_endpoint_set_owns_shm(ep, TRUE); - ep->ip_mutex = ip_hdl; - - mutex_enter(&com_shm_destination_mutex); - - /* Increment the count of successful bindings */ - - com_shm_bind_count++; - - mutex_exit(&com_shm_destination_mutex); - - com_shm_set_not_empty(map, FALSE); - com_shm_set_empty_waiters(map, 0); - com_shm_set_max_len(map, com_shm_endpoint_get_size(ep)); - - com_shm_set_valid(map, COM_SHM_VALID); - - os_event_set(com_shm_endpoint_get_empty(ep)); - - return(0); -} - -/************************************************************************* -Waits for a datagram to arrive at an endpoint. */ - -ulint -com_shm_recvfrom( -/*=============*/ - /* out: 0 if succeed, else error number */ - com_shm_endpoint_t* ep, /* in: communications endpoint */ - byte* buf, /* out: datagram buffer; the buffer is - supplied by the caller */ - ulint buf_len,/* in: datagram buffer length */ - ulint* len, /* out: datagram length */ - char* from, /* out: address name buffer; the buffer is - supplied by the caller */ - ulint from_len,/* in: address name buffer length */ - ulint* addr_len)/* out: address name length */ -{ - com_shm_t* map; - ulint loop_count; - - map = com_shm_endpoint_get_map(ep); - - loop_count = 0; -loop: - com_shm_system_call_count++; - - /* NOTE: automatic event */ - - os_event_wait(com_shm_endpoint_get_not_empty(ep)); - - loop_count++; - - if (loop_count > 1) { - printf("!!!!!!!!COM_SHM loop count %lu\n", (ulong) loop_count); - } - - ut_ad(loop_count < 2); - - com_shm_enter(ep); - - if (!com_shm_get_not_empty(map)) { - /* There was no datagram, wait for the event */ - - com_shm_exit(ep); - - goto loop; - } - - if (com_shm_get_data_len(map) > buf_len) { - - com_shm_exit(ep); - - return(COM_ERR_DATA_BUFFER_TOO_SMALL); - } - - if (com_shm_get_addr_len(map) > from_len) { - - com_shm_exit(ep); - - return(COM_ERR_ADDR_BUFFER_TOO_SMALL); - } - - *len = com_shm_get_data_len(map); - *addr_len = com_shm_get_addr_len(map); - - ut_memcpy(buf, com_shm_get_data(map), *len); - ut_memcpy(from, com_shm_get_addr(map), *addr_len); - - com_shm_set_not_empty(map, FALSE); - - /* If there may be writers queuing to insert the datagram, signal the - empty-event */ - - if (com_shm_get_empty_waiters(map) != 0) { - - com_shm_system_call_count++; - - os_event_set(com_shm_endpoint_get_empty(ep)); - } - - com_shm_exit(ep); - - return(0); -} - -/************************************************************************* -Sends a datagram to the specified destination. */ - -ulint -com_shm_sendto( -/*===========*/ - /* out: 0 if succeed, else error number */ - com_shm_endpoint_t* ep, /* in: communications endpoint */ - byte* buf, /* in: datagram buffer */ - ulint len, /* in: datagram length */ - char* to, /* in: address name buffer */ - ulint tolen) /* in: address name length */ -{ - com_shm_endpoint_t* ep2; - com_shm_t* map; - ulint sender_len; - ulint ret; - ulint loop_count; - - /* Try first to find from the cached destination addresses */ - - ep2 = com_shm_destination_cache_search(to, tolen); - - if (ep2 == NULL) { - /* Did not find it in the cache */ - ep2 = com_shm_endpoint_create(); - - ret = com_shm_open(ep2, to, tolen); - - if (ret != 0) { - com_shm_endpoint_free(ep2); - - return(ret); - } - - /* Insert into the cached destination addresses */ - - com_shm_destination_cache_insert(ep2); - } - - map = com_shm_endpoint_get_map(ep2); - - if (com_shm_get_valid(map) != COM_SHM_VALID) { - - com_shm_exit(ep2); - - return(COM_ERR_DGRAM_NOT_DELIVERED); - } - - if (com_shm_get_max_len(map) < len) { - - com_shm_exit(ep2); - - return(COM_ERR_DATA_TOO_LONG); - } - - /* Optimistically, we first go to see if the datagram area is empty, - without waiting for the empty-event */ - - loop_count = 0; -loop: - loop_count++; - - if (loop_count > 5) { - printf("!!!!!!COM_SHM Notempty loop count %lu\n", - (ulong) loop_count); - } - - ut_ad(loop_count < 100); - - com_shm_enter(ep2); - - if (com_shm_get_not_empty(map)) { - - /* Not empty, we cannot insert a datagram */ - - com_shm_set_empty_waiters(map, - 1 + com_shm_get_empty_waiters(map)); - com_shm_exit(ep2); - - com_shm_system_call_count++; - - /* Wait for the area to become empty */ - /* NOTE: automatic event */ - - ret = os_event_wait_time(com_shm_endpoint_get_empty(ep2), - 10000000); - ut_a(ret == 0); - - com_shm_enter(ep2); - - com_shm_set_empty_waiters(map, - com_shm_get_empty_waiters(map) - 1); - com_shm_exit(ep2); - - goto loop; - } - - sender_len = com_shm_endpoint_get_addr_len(ep); - - com_shm_set_data_len(map, len); - com_shm_set_addr_len(map, sender_len); - - ut_memcpy(com_shm_get_data(map), buf, len); - ut_memcpy(com_shm_get_addr(map), com_shm_endpoint_get_addr(ep), - sender_len); - com_shm_set_not_empty(map, TRUE); - com_shm_system_call_count++; - - com_shm_exit(ep2); - - /* Signal the event */ - - os_event_set(com_shm_endpoint_get_not_empty(ep2)); - - return(0); -} |