int main(int argc, char **argv) { int i; int64_t p1 = 0; uint64_t p2 = 0; int32_t p3 = 0; uint32_t p4 = 0; int16_t p5 = 0; uint16_t p6 = 0; int8_t p7 = 0; uint16_t p8 = 0; atomic_store_int64_t(&p1, 55); atomic_store_uint64_t(&p2, 55); atomic_store_int32_t(&p3, 55); atomic_store_uint32_t(&p4, 55); atomic_store_int16_t(&p5, 55); atomic_store_uint16_t(&p6, 55); atomic_store_int8_t(&p7, 55); atomic_store_uint8_t(&p8, 55); assert(p1 == 55); assert(p2 == 55); assert(p3 == 55); assert(p4 == 55); assert(p5 == 55); assert(p6 == 55); assert(p7 == 55); assert(p8 == 55); #define test(t,f) \ do {\ for (i = 0; i < 500000; i++) { \ t res1; \ t res2; \ t x1; \ t x2; \ t f1; \ t f2; \ \ res1 = res2 = random(); \ x1 = x2 = random(); \ f1 = f2 = random(); \ \ x1 = x1__##f(&res1, f1); \ x2 = x2__##f(&res2, f2); \ \ fprintf(stderr, "%d: %lld == %lld, %lld == %lld\n", \ __LINE__, (long long) x1, \ (long long) x2, (long long) res1, \ (long long) res2); \ assert(x1 == x2); \ assert(res1 == res2); \ } \ } while (0) test(int64_t, atomic_postadd_int64_t); test(int64_t, atomic_add_int64_t); test(int64_t, atomic_postsub_int64_t); test(int64_t, atomic_sub_int64_t); test(uint64_t, atomic_postadd_uint64_t); test(uint64_t, atomic_add_uint64_t); test(uint64_t, atomic_postsub_uint64_t); test(uint64_t, atomic_sub_uint64_t); test(uint64_t, atomic_postset_uint64_t_bits); test(uint64_t, atomic_set_uint64_t_bits); test(uint64_t, atomic_postclear_uint64_t_bits); test(uint64_t, atomic_clear_uint64_t_bits); test(int32_t, atomic_postadd_int32_t); test(int32_t, atomic_add_int32_t); test(int32_t, atomic_postsub_int32_t); test(int32_t, atomic_sub_int32_t); test(uint32_t, atomic_postadd_uint32_t); test(uint32_t, atomic_add_uint32_t); test(uint32_t, atomic_postsub_uint32_t); test(uint32_t, atomic_sub_uint32_t); test(uint32_t, atomic_postset_uint32_t_bits); test(uint32_t, atomic_set_uint32_t_bits); test(uint32_t, atomic_postclear_uint32_t_bits); test(uint32_t, atomic_clear_uint32_t_bits); test(int16_t, atomic_postadd_int16_t); test(int16_t, atomic_add_int16_t); test(int16_t, atomic_postsub_int16_t); test(int16_t, atomic_sub_int16_t); test(uint16_t, atomic_postadd_uint16_t); test(uint16_t, atomic_add_uint16_t); test(uint16_t, atomic_postsub_uint16_t); test(uint16_t, atomic_sub_uint16_t); test(uint16_t, atomic_postset_uint16_t_bits); test(uint16_t, atomic_set_uint16_t_bits); test(uint16_t, atomic_postclear_uint16_t_bits); test(uint16_t, atomic_clear_uint16_t_bits); test(int8_t, atomic_postadd_int8_t); test(int8_t, atomic_add_int8_t); test(int8_t, atomic_postsub_int8_t); test(int8_t, atomic_sub_int8_t); test(uint8_t, atomic_postadd_uint8_t); test(uint8_t, atomic_add_uint8_t); test(uint8_t, atomic_postsub_uint8_t); test(uint8_t, atomic_sub_uint8_t); test(uint8_t, atomic_postset_uint8_t_bits); test(uint8_t, atomic_set_uint8_t_bits); test(uint8_t, atomic_postclear_uint8_t_bits); test(uint8_t, atomic_clear_uint8_t_bits); return 0; }
/* Equivalent du _9p_socket_thread( */ void * _9p_rdma_thread( void * Arg ) { msk_trans_t * trans = Arg ; _9p_rdma_priv * priv = NULL ; _9p_conn_t * p_9p_conn = NULL ; uint8_t * rdmabuf = NULL ; struct ibv_mr * mr = NULL ; msk_data_t * rdata = NULL ; _9p_datalock_t * datalock = NULL ; unsigned int i = 0 ; int rc = 0 ; if( ( priv = gsh_malloc( sizeof(*priv) ) ) == NULL ) { LogFatal( COMPONENT_9P, "9P/RDMA: trans handler could not malloc private structure" ) ; goto error ; } memset(priv, 0, sizeof(*priv)); trans->private_data = priv; if( ( p_9p_conn = gsh_malloc( sizeof(*p_9p_conn) ) ) == NULL ) { LogFatal( COMPONENT_9P, "9P/RDMA: trans handler could not malloc _9p_conn" ) ; goto error ; } memset(p_9p_conn, 0, sizeof(*p_9p_conn)); priv->pconn = p_9p_conn; for (i = 0; i < FLUSH_BUCKETS; i++) { pthread_mutex_init(&p_9p_conn->flush_buckets[i].lock, NULL); glist_init(&p_9p_conn->flush_buckets[i].list); } p_9p_conn->sequence = 0 ; atomic_store_uint32_t(&p_9p_conn->refcount, 0) ; p_9p_conn->trans_type = _9P_RDMA ; p_9p_conn->trans_data.rdma_trans = trans ; memcpy(&p_9p_conn->addrpeer, msk_get_dst_addr(trans), sizeof(p_9p_conn->addrpeer)); /* Init the fids pointers array */ memset( &p_9p_conn->fids, 0, _9P_FID_PER_CONN* sizeof( _9p_fid_t * ) ) ; /* Set initial msize. Client may request a lower value during TVERSION */ p_9p_conn->msize = nfs_param._9p_param._9p_rdma_msize ; if( gettimeofday( &p_9p_conn->birth, NULL ) == -1 ) LogMajor( COMPONENT_9P, "Cannot get connection's time of birth" ) ; /* Alloc rdmabuf */ if( ( rdmabuf = gsh_malloc( (_9P_RDMA_BUFF_NUM)*_9P_RDMA_CHUNK_SIZE)) == NULL ) { LogFatal( COMPONENT_9P, "9P/RDMA: trans handler could not malloc rdmabuf" ) ; goto error ; } memset( rdmabuf, 0, (_9P_RDMA_BUFF_NUM)*_9P_RDMA_CHUNK_SIZE); priv->rdmabuf = rdmabuf; /* Register rdmabuf */ if( ( mr = msk_reg_mr( trans, rdmabuf, (_9P_RDMA_BUFF_NUM)*_9P_RDMA_CHUNK_SIZE, IBV_ACCESS_LOCAL_WRITE)) == NULL ) { LogFatal( COMPONENT_9P, "9P/RDMA: trans handler could not register rdmabuf" ) ; goto error ; } /* Get prepared to recv data */ if( ( rdata = gsh_malloc( _9P_RDMA_BUFF_NUM * sizeof(*rdata) ) ) == NULL ) { LogFatal( COMPONENT_9P, "9P/RDMA: trans handler could not malloc rdata" ) ; goto error ; } memset( rdata, 0, (_9P_RDMA_BUFF_NUM * sizeof(*rdata)) ) ; priv->rdata = rdata; if( (datalock = gsh_malloc(_9P_RDMA_BUFF_NUM*sizeof(*datalock))) == NULL ) { LogFatal( COMPONENT_9P, "9P/RDMA: trans handler could not malloc datalock" ) ; goto error ; } memset( datalock, 0, (_9P_RDMA_BUFF_NUM * sizeof(*datalock)) ) ; priv->datalock = datalock; for( i=0; i < _9P_RDMA_BUFF_NUM; i++) { rdata[i].data=rdmabuf+i*_9P_RDMA_CHUNK_SIZE ; rdata[i].max_size=_9P_RDMA_CHUNK_SIZE ; rdata[i].mr = mr; datalock[i].data = &rdata[i]; pthread_mutex_init(&datalock[i].lock, NULL); if( i < _9P_RDMA_OUT ) datalock[i].sender = &datalock[i+_9P_RDMA_OUT] ; else datalock[i].sender = NULL ; } /* for (unsigned int i=0; i < _9P_RDMA_BUFF_NUM; i++) */ for( i=0; i < _9P_RDMA_OUT; i++) { if( ( rc = msk_post_recv( trans, &rdata[i], _9p_rdma_callback_recv, _9p_rdma_callback_recv_err, &(datalock[i]) ) ) != 0 ) { LogEvent( COMPONENT_9P, "9P/RDMA: trans handler could recv first byte of datalock[%u], rc=%u", i, rc ) ; goto error ; } } /* Finalize accept */ if( ( rc = msk_finalize_accept( trans ) ) != 0 ) { LogMajor( COMPONENT_9P, "9P/RDMA: trans handler could not finalize accept, rc=%u", rc ) ; goto error ; } pthread_exit( NULL ) ; error: _9p_rdma_cleanup_conn_thread( trans ) ; pthread_exit( NULL ) ; } /* _9p_rdma_handle_trans */
void *_9p_socket_thread(void *Arg) { long int tcp_sock = (long int)Arg; int rc = -1; struct pollfd fds[1]; int fdcount = 1; static char my_name[MAXNAMLEN + 1]; socklen_t addrpeerlen = 0; struct sockaddr_storage addrpeer; char strcaller[INET6_ADDRSTRLEN]; request_data_t *req = NULL; int tag; unsigned long sequence = 0; unsigned int i = 0; char *_9pmsg = NULL; uint32_t msglen; struct _9p_conn _9p_conn; int readlen = 0; int total_readlen = 0; snprintf(my_name, MAXNAMLEN, "9p_sock_mgr#fd=%ld", tcp_sock); SetNameFunction(my_name); /* Init the struct _9p_conn structure */ memset(&_9p_conn, 0, sizeof(_9p_conn)); pthread_mutex_init(&_9p_conn.sock_lock, NULL); _9p_conn.trans_type = _9P_TCP; _9p_conn.trans_data.sockfd = tcp_sock; for (i = 0; i < FLUSH_BUCKETS; i++) { pthread_mutex_init(&_9p_conn.flush_buckets[i].lock, NULL); glist_init(&_9p_conn.flush_buckets[i].list); } atomic_store_uint32_t(&_9p_conn.refcount, 0); /* Init the fids pointers array */ memset(&_9p_conn.fids, 0, _9P_FID_PER_CONN * sizeof(struct _9p_fid *)); /* Set initial msize. * Client may request a lower value during TVERSION */ _9p_conn.msize = _9p_param._9p_tcp_msize; if (gettimeofday(&_9p_conn.birth, NULL) == -1) LogFatal(COMPONENT_9P, "Cannot get connection's time of birth"); addrpeerlen = sizeof(addrpeer); rc = getpeername(tcp_sock, (struct sockaddr *)&addrpeer, &addrpeerlen); if (rc == -1) { LogMajor(COMPONENT_9P, "Cannot get peername to tcp socket for 9p, error %d (%s)", errno, strerror(errno)); /* XXX */ strncpy(strcaller, "(unresolved)", INET6_ADDRSTRLEN); strcaller[12] = '\0'; } else { switch (addrpeer.ss_family) { case AF_INET: inet_ntop(addrpeer.ss_family, &((struct sockaddr_in *)&addrpeer)-> sin_addr, strcaller, INET6_ADDRSTRLEN); break; case AF_INET6: inet_ntop(addrpeer.ss_family, &((struct sockaddr_in6 *)&addrpeer)-> sin6_addr, strcaller, INET6_ADDRSTRLEN); break; default: snprintf(strcaller, INET6_ADDRSTRLEN, "BAD ADDRESS"); break; } LogEvent(COMPONENT_9P, "9p socket #%ld is connected to %s", tcp_sock, strcaller); printf("9p socket #%ld is connected to %s\n", tcp_sock, strcaller); } _9p_conn.client = get_gsh_client(&addrpeer, false); /* Set up the structure used by poll */ memset((char *)fds, 0, sizeof(struct pollfd)); fds[0].fd = tcp_sock; fds[0].events = POLLIN | POLLPRI | POLLRDBAND | POLLRDNORM | POLLRDHUP | POLLHUP | POLLERR | POLLNVAL; for (;;) { total_readlen = 0; /* new message */ rc = poll(fds, fdcount, -1); if (rc == -1) { /* timeout = -1 => Wait indefinitely for events */ /* Interruption if not an issue */ if (errno == EINTR) continue; LogCrit(COMPONENT_9P, "Got error %u (%s) on fd %ld connect to %s while polling on socket", errno, strerror(errno), tcp_sock, strcaller); } if (fds[0].revents & POLLNVAL) { LogEvent(COMPONENT_9P, "Client %s on socket %lu produced POLLNVAL", strcaller, tcp_sock); goto end; } if (fds[0].revents & (POLLERR | POLLHUP | POLLRDHUP)) { LogEvent(COMPONENT_9P, "Client %s on socket %lu has shut down and closed", strcaller, tcp_sock); goto end; } if (!(fds[0].revents & (POLLIN | POLLRDNORM))) continue; /* Prepare to read the message */ _9pmsg = gsh_malloc(_9p_conn.msize); if (_9pmsg == NULL) { LogCrit(COMPONENT_9P, "Could not allocate 9pmsg buffer for client %s on socket %lu", strcaller, tcp_sock); goto end; } /* An incoming 9P request: the msg has a 4 bytes header showing the size of the msg including the header */ readlen = recv(fds[0].fd, _9pmsg, _9P_HDR_SIZE, MSG_WAITALL); if (readlen != _9P_HDR_SIZE) goto badmsg; msglen = *(uint32_t *) _9pmsg; if (msglen > _9p_conn.msize) { LogCrit(COMPONENT_9P, "Message size too big! got %u, max = %u", msglen, _9p_conn.msize); goto end; } LogFullDebug(COMPONENT_9P, "Received 9P/TCP message of size %u from client %s on socket %lu", msglen, strcaller, tcp_sock); total_readlen += readlen; while (total_readlen < msglen) { readlen = recv(fds[0].fd, _9pmsg + total_readlen, msglen - total_readlen, 0); if (readlen > 0) { total_readlen += readlen; continue; } if (readlen == 0 || (readlen < 0 && errno != EINTR)) goto badmsg; } /* while */ server_stats_transport_done(_9p_conn.client, total_readlen, 1, 0, 0, 0, 0); /* Message is good. */ req = pool_alloc(request_pool, NULL); req->rtype = _9P_REQUEST; req->r_u._9p._9pmsg = _9pmsg; req->r_u._9p.pconn = &_9p_conn; /* Add this request to the request list, * should it be flushed later. */ tag = *(u16 *) (_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE); _9p_AddFlushHook(&req->r_u._9p, tag, sequence++); LogFullDebug(COMPONENT_9P, "Request tag is %d\n", tag); /* Message was OK push it */ DispatchWork9P(req); /* Not our buffer anymore */ _9pmsg = NULL; continue; badmsg: if (readlen == 0) LogEvent(COMPONENT_9P, "Premature end for Client %s on socket %lu, total read = %u", strcaller, tcp_sock, total_readlen); else if (readlen < 0) { LogEvent(COMPONENT_9P, "Read error client %s on socket %lu errno=%d, total read = %u", strcaller, tcp_sock, errno, total_readlen); } else LogEvent(COMPONENT_9P, "Header too small! for client %s on socket %lu: readlen=%u expected=%u", strcaller, tcp_sock, readlen, _9P_HDR_SIZE); /* Either way, we close the connection. * It is not possible to survive * once we get out of sync in the TCP stream * with the client */ break; /* bail out */ } /* for( ;; ) */ end: LogEvent(COMPONENT_9P, "Closing connection on socket %lu", tcp_sock); close(tcp_sock); /* Free buffer if we encountered an error * before we could give it to a worker */ if (_9pmsg) gsh_free(_9pmsg); while (atomic_fetch_uint32_t(&_9p_conn.refcount)) { LogEvent(COMPONENT_9P, "Waiting for workers to release pconn"); sleep(1); } _9p_cleanup_fids(&_9p_conn); if (_9p_conn.client != NULL) put_gsh_client(_9p_conn.client); pthread_exit(NULL); } /* _9p_socket_thread */