X-Git-Url: http://winboard.nl/cgi-bin?p=bonanza.git;a=blobdiff_plain;f=thread.c;h=f170edd03e3d67d21f5225bb9cd32932ff2d0bc4;hp=c88461aab98f62ff0bb6e9794250e542206a42b7;hb=31daebfc1031441aa180e3af2e547a8cd2b92c32;hpb=18b507e1b20fc6c32ee50f00fb910a59110c1a1d diff --git a/thread.c b/thread.c index c88461a..f170edd 100644 --- a/thread.c +++ b/thread.c @@ -1,13 +1,369 @@ #include #include #include +#include +#include #if defined(_WIN32) # include #else +# include +# include +# include # include #endif #include "shogi.h" + +#if defined(TLP) || defined(DFPN_CLIENT) +int CONV +lock_init( lock_t *plock ) +{ +# if defined(_MSC_VER) + *plock = 0; +# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + *plock = 0; +# else + if ( pthread_mutex_init( plock, 0 ) ) + { + str_error = "pthread_mutex_init() failed."; + return -1; + } +# endif + return 1; +} + + +int CONV +lock_free( lock_t *plock ) +{ +# if defined(_MSC_VER) + *plock = 0; +# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + *plock = 0; +# else + if ( pthread_mutex_destroy( plock ) ) + { + str_error = "pthread_mutex_destroy() failed."; + return -1; + } +# endif + return 1; +} + + +void CONV +unlock( lock_t *plock ) +{ +# if defined(_MSC_VER) + *plock = 0; +# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + *plock = 0; +# else + pthread_mutex_unlock( plock ); +# endif +} + + +void CONV +lock( lock_t *plock ) +{ +# if defined(_MSC_VER) + while ( _InterlockedExchange( (void *)plock, 1 ) ) + { + while ( *plock ) { tlp_yield();} + } +# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + int itemp; + + for ( ;; ) + { + asm ( "1: movl $1, %1 \n\t" + " xchgl (%0), %1 \n\t" + : "=g" (plock), "=r" (itemp) : "0" (plock) ); + if ( ! itemp ) { return; } + while ( *plock ) { tlp_yield();} + } +# else + pthread_mutex_lock( plock ); +# endif +} + + +void +tlp_yield( void ) +{ +#if defined(_WIN32) + Sleep( 0 ); +#else + sched_yield(); +#endif +} +#endif /* TLP || DFPN_CLIENT */ + + +#if defined(DFPN_CLIENT) + +static int CONV proce_line( char *line_buf ); +# if defined(_WIN32) +static unsigned int __stdcall dfpn_client_receiver( void *arg ); +# else +static void *dfpn_client_receiver( void *arg ); +# endif + +void CONV +dfpn_client_start( const tree_t * restrict ptree ) +{ + if ( root_turn != min_posi_no_handicap.turn_to_move + || HAND_B != min_posi_no_handicap.hand_black + || HAND_W != min_posi_no_handicap.hand_white + || memcmp( BOARD, min_posi_no_handicap.asquare, nsquare ) ) + { + sckt_shutdown( dfpn_client_sckt ); + dfpn_client_sckt = SCKT_NULL; + return; + } + + if ( dfpn_client_sckt != SCKT_NULL ) { return; } + if ( dfpn_client_str_addr[0] == '\0' ) { return; } + + dfpn_client_sckt = sckt_connect( dfpn_client_str_addr, dfpn_client_port ); + if ( dfpn_client_sckt == SCKT_NULL ) + { + out_warning( "Connection to DFPN server failed." ); + return; + } + else { + Out( "New connection to DFPN server: %s %d\n", + dfpn_client_str_addr, dfpn_client_port ); + } + +# if defined(_WIN32) + if ( ! _beginthreadex( 0, 0, &dfpn_client_receiver, NULL, 0, 0 ) ) + { + sckt_shutdown( dfpn_client_sckt ); + dfpn_client_sckt = SCKT_NULL; + out_warning( "_beginthreadex() failed." ); + } +# else + { + pthread_t pt; + if ( pthread_create( &pt, &pthread_attr, &dfpn_client_receiver, NULL ) ) + { + sckt_shutdown( dfpn_client_sckt ); + dfpn_client_sckt = SCKT_NULL; + out_warning( "_beginthreadex() failed." ); + } + } +# endif + + dfpn_client_out( "Client: anonymous\n" ); +} + + +# if defined(_MSC_VER) +# pragma warning(disable:4100) +# elif defined(__ICC) +# pragma warning(disable:869) +# endif + +# if defined(_MSC_VER) +static unsigned int __stdcall dfpn_client_receiver( void *arg ) +# else +static void *dfpn_client_receiver( void *arg ) +#endif +{ +#define SIZE_RECV_BUF ( 1024 * 16 ) +#define SIZE_LINE_BUF 1024 + char recv_buf[ SIZE_RECV_BUF ]; + char line_buf[ SIZE_LINE_BUF ]; + char *str_end, *str_line_end; + size_t size; + int len_recv_buf; + struct timeval tv; + fd_set readfds; + int iret; + + recv_buf[0] = '\0'; + + /* recv loop */ + for ( ;; ) { + + /* select loop */ + for ( ;; ) { + tv.tv_sec = SEC_KEEP_ALIVE; + tv.tv_usec = 0; + FD_ZERO( &readfds ); +# if defined(_MSC_VER) +# pragma warning(disable:4127) +# endif + FD_SET( dfpn_client_sckt, &readfds ); +# if defined(_MSC_VER) +# pragma warning(default:4127) +# endif + + iret = select( (int)dfpn_client_sckt+1, &readfds, NULL, NULL, &tv ); + if ( iret == SOCKET_ERROR ) + { + out_warning( "%s", str_error ); + goto dfpn_client_receiver_shutdown; + } + + /* message arrived */ + if ( iret ) { break; } + + /* timeout and keepalive */ + lock( &dfpn_client_lock); + iret = dfpn_client_out( "ping\n" ); + unlock( &dfpn_client_lock); + if ( iret < 0 ) { return 0; } + } + + /* read messages */ + len_recv_buf = (int)strlen( recv_buf ); + str_end = recv_buf + len_recv_buf; + + iret = recv( dfpn_client_sckt, str_end, SIZE_RECV_BUF-1-len_recv_buf, 0 ); + if ( iret == SOCKET_ERROR ) + { + str_error = str_WSAError( "recv() failed:" ); + out_warning( "%s", str_error ); + goto dfpn_client_receiver_shutdown; + } + if ( ! iret ) { goto dfpn_client_receiver_shutdown; } + recv_buf[ len_recv_buf + iret ] = '\0'; + + /* take each line */ + lock( &dfpn_client_lock ); + for ( ;; ) { + + str_line_end = strchr( recv_buf, '\n' ); + if ( str_line_end == NULL ) + { + if ( iret + len_recv_buf + 1 >= SIZE_RECV_BUF ) + { + unlock( &dfpn_client_lock ); + out_warning( "%s", str_ovrflw_line ); + goto dfpn_client_receiver_shutdown; + } + break; + } + + size = str_line_end - recv_buf; + if ( size + 1 >= SIZE_LINE_BUF ) + { + unlock( &dfpn_client_lock ); + out_warning( "%s", str_ovrflw_line ); + goto dfpn_client_receiver_shutdown; + } + + memcpy( line_buf, recv_buf, size ); + memmove( recv_buf, str_line_end+1, strlen(str_line_end+1) + 1 ); + + line_buf[size] = '\0'; + + if ( proce_line( line_buf ) < 0 ) + { + unlock( &dfpn_client_lock ); + out_warning( "invalid messages from DFPN server" ); + goto dfpn_client_receiver_shutdown; + } + } + unlock( &dfpn_client_lock ); + } + + dfpn_client_receiver_shutdown: + sckt_shutdown( dfpn_client_sckt ); + dfpn_client_sckt = SCKT_NULL; + out_warning( "A connection to DFPN server is down." ); + + return 0; +} +# if defined(_MSC_VER) +# pragma warning(default:4100) +# elif defined(__ICC) +# pragma warning(default:869) +#endif + + +static int CONV proce_line( char *line_buf ) +{ + const char *token; + volatile dfpn_client_cresult_t *pcresult; + char *last; + + token = strtok_r( line_buf, str_delimiters, &last ); + if ( token == NULL ) { return -1; } + + /* check signature */ + if ( strcmp( token, (const char *)dfpn_client_signature ) ) { return 1; } + + token = strtok_r( NULL, str_delimiters, &last ); + if ( token == NULL ) { return -1; } + + /* root node */ + if ( ! strcmp( token, "WIN" ) ) + { + token = strtok_r( NULL, str_delimiters, &last ); + if ( token == NULL || ! is_move( token ) ) { return -1; } + dfpn_client_rresult = dfpn_client_win; + dfpn_client_flag_read = 1; + memcpy( (char *)dfpn_client_str_move, token, 7 ); + return 1; + } + + if ( ! strcmp( token, "LOSE" ) ) + { + dfpn_client_rresult = dfpn_client_lose; + dfpn_client_flag_read = 1; + return 1; + } + + if ( ! strcmp( token, "UNSOLVED" ) ) + { + dfpn_client_rresult = dfpn_client_misc; + dfpn_client_flag_read = 1; + return 1; + } + + /* child node */ + if ( ! is_move( token ) ) { return -1; } + if ( MAX_LEGAL_MOVES <= dfpn_client_num_cresult ) { return -1; } + pcresult = &dfpn_client_cresult[dfpn_client_num_cresult]; + memcpy( (char *)pcresult->str_move, token, 7 ); + + token = strtok_r( NULL, str_delimiters, &last ); + if ( token == NULL ) { return -1; } + + if ( ! strcmp( token, "WIN" ) ) + { + pcresult->result = dfpn_client_win; + dfpn_client_flag_read = 1; + dfpn_client_num_cresult += 1; + return 1; + } + + if ( ! strcmp( token, "LOSE" ) ) + { + pcresult->result = dfpn_client_lose; + dfpn_client_flag_read = 1; + dfpn_client_num_cresult += 1; + return 1; + } + + if ( ! strcmp( token, "UNSOLVED" ) ) + { + pcresult->result = dfpn_client_misc; + dfpn_client_flag_read = 1; + dfpn_client_num_cresult += 1; + return 1; + } + + return -1; +} + +#endif /* DFPN_CLINET */ + + #if defined(TLP) # if defined(_WIN32) @@ -138,7 +494,7 @@ tlp_set_abort( tree_t * restrict ptree ) } -#if defined(MNJ_LAN) +#if defined(MNJ_LAN) || defined(USI) uint64_t tlp_count_node( tree_t * restrict ptree ) { @@ -169,95 +525,6 @@ tlp_is_descendant( const tree_t * restrict ptree, int slot_ancestor ) } -int -lock_init( lock_t *plock ) -{ -# if defined(_MSC_VER) - *plock = 0; -# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) - *plock = 0; -# else - if ( pthread_mutex_init( plock, 0 ) ) - { - str_error = "pthread_mutex_init() failed."; - return -1; - } -# endif - return 1; -} - - -int -lock_free( lock_t *plock ) -{ -# if defined(_MSC_VER) - *plock = 0; -# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) - *plock = 0; -# else - if ( pthread_mutex_destroy( plock ) ) - { - str_error = "pthread_mutex_destroy() failed."; - return -1; - } -# endif - return 1; -} - - -void -unlock( lock_t *plock ) -{ -# if defined(_MSC_VER) - *plock = 0; -# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) - *plock = 0; -# else - pthread_mutex_unlock( plock ); -# endif -} - - -void -lock( lock_t *plock ) -{ -# if defined(_MSC_VER) - long l; - - for ( ;; ) - { - l = _InterlockedExchange( (void *)plock, 1 ); - if ( ! l ) { return; } - while ( *plock ); - } -# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) - int itemp; - - for ( ;; ) - { - asm ( "1: movl $1, %1 \n\t" - " xchgl (%0), %1 \n\t" - : "=g" (plock), "=r" (itemp) : "0" (plock) ); - if ( ! itemp ) { return; } - while ( *plock ); - } -# else - pthread_mutex_lock( plock ); -# endif -} - - -void -tlp_yield( void ) -{ -#if defined(_WIN32) - Sleep( 0 ); -#else - sched_yield(); -#endif -} - - # if defined(_MSC_VER) static unsigned int __stdcall start_address( void *arg ) # else @@ -361,8 +628,6 @@ init_state( const tree_t * restrict parent, tree_t * restrict child ) child->nperpetual_check = 0; child->nsuperior_rep = 0; child->nrep_tried = 0; - child->nreject_tried = 0; - child->nreject_done = 0; child->ntrans_always_hit = 0; child->ntrans_prefer_hit = 0; child->ntrans_probe = 0; @@ -381,15 +646,16 @@ init_state( const tree_t * restrict parent, tree_t * restrict child ) child->anext_move[ply].move_cap2 = parent->anext_move[ply].move_cap2; child->move_last[ply] = child->amove; - child->stand_pat[ply] = parent->stand_pat[ply]; + child->save_eval[ply] = parent->save_eval[ply]; child->current_move[ply-1] = parent->current_move[ply-1]; child->nsuc_check[ply-1] = parent->nsuc_check[ply-1]; child->nsuc_check[ply] = parent->nsuc_check[ply]; + child->nrep = parent->nrep; memcpy( child->hist_good, parent->hist_good, sizeof(parent->hist_good) ); memcpy( child->hist_tried, parent->hist_tried, sizeof(parent->hist_tried) ); - for ( i = 0; i < root_nrep + ply - 1; i++ ) + for ( i = 0; i < child->nrep + ply - 1; i++ ) { child->rep_board_list[i] = parent->rep_board_list[i]; child->rep_hand_list[i] = parent->rep_hand_list[i]; @@ -424,8 +690,6 @@ copy_state( tree_t * restrict parent, const tree_t * restrict child, parent->nfour_fold_rep += child->nfour_fold_rep; parent->nperpetual_check += child->nperpetual_check; parent->nsuperior_rep += child->nsuperior_rep; - parent->nreject_tried += child->nreject_tried; - parent->nreject_done += child->nreject_done; parent->ntrans_always_hit += child->ntrans_always_hit; parent->ntrans_prefer_hit += child->ntrans_prefer_hit; parent->ntrans_probe += child->ntrans_probe; @@ -439,19 +703,20 @@ copy_state( tree_t * restrict parent, const tree_t * restrict child, if ( child->tlp_abort || value <= parent->tlp_best ) { return; } - ply = parent->tlp_ply; - parent->tlp_best = (short)value; - parent->pv[ply] = child->pv[ply]; + ply = parent->tlp_ply; + parent->tlp_best = (short)value; + parent->pv[ply] = child->pv[ply]; + + lock( &parent->tlp_lock ); parent->current_move[ply] = child->current_move[ply]; - memcpy( parent->hist_tried, child->hist_tried, sizeof(child->hist_tried) ); memcpy( parent->hist_good, child->hist_good, sizeof(child->hist_good) ); - for ( i = ply; i < PLY_MAX; i++ ) { parent->amove_killer[i] = child->amove_killer[i]; parent->killers[i] = child->killers[i]; } + unlock( &parent->tlp_lock ); }