From: Mikael Ronstrom Date: September 12 2012 12:42pm Subject: bzr push into mysql-5.5-cluster-7.2 branch (mikael.ronstrom:3968 to 3970) List-Archive: http://lists.mysql.com/commits/144739 Message-Id: <201209121243.q8CChEa4004241@dator6> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3970 Mikael Ronstrom 2012-09-12 Make it possible to unlock, that is to remove CPU locking modified: storage/ndb/src/common/portlib/NdbThread.c 3969 Mikael Ronstrom 2012-09-11 More handling of config variables added: mysql-test/suite/ndb/r/ndb_recv_thread_cpu_mask_basic.result mysql-test/suite/ndb/t/ndb_recv_thread_cpu_mask_basic.test modified: mysql-test/suite/ndb/r/ndb_basic.result sql/ha_ndbcluster.cc 3968 Mikael Ronstrom 2012-08-28 Fixed m_node_active modified: storage/ndb/src/ndbapi/TransporterFacade.cpp === modified file 'mysql-test/suite/ndb/r/ndb_basic.result' --- a/mysql-test/suite/ndb/r/ndb_basic.result revid:mikael.ronstrom@stripped +++ b/mysql-test/suite/ndb/r/ndb_basic.result revid:mikael.ronstrom@stripped @@ -129,8 +129,11 @@ ndb_log_update_as_write # ndb_log_updated_only # ndb_mgmd_host # ndb_nodeid # +ndb_num_recv_threads # ndb_optimization_delay # ndb_optimized_node_selection # +ndb_recv_thread_activation_threshold # +ndb_recv_thread_cpu_mask # ndb_report_thresh_binlog_epoch_slip # ndb_report_thresh_binlog_mem_usage # ndb_table_no_logging # === added file 'mysql-test/suite/ndb/r/ndb_recv_thread_cpu_mask_basic.result' --- a/mysql-test/suite/ndb/r/ndb_recv_thread_cpu_mask_basic.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/r/ndb_recv_thread_cpu_mask_basic.result revid:mikael.ronstrom@stripped @@ -0,0 +1,81 @@ +SET @global_start_value = @@global.ndb_recv_thread_cpu_mask; +SELECT @global_start_value; +@global_start_value + +'#--------------------FN_DYNVARS_183_01------------------------#' +SET @@global.ndb_recv_thread_cpu_mask = '1'; +SET @@global.ndb_recv_thread_cpu_mask = DEFAULT; +SELECT @@global.ndb_recv_thread_cpu_mask; +@@global.ndb_recv_thread_cpu_mask + +'#---------------------FN_DYNVARS_183_02-------------------------#' +SET @@global.ndb_recv_thread_cpu_mask = NULL; +ERROR 42000: Variable 'ndb_recv_thread_cpu_mask' can't be set to the value of 'NULL' +SET @@global.ndb_recv_thread_cpu_mask = ''; +'#--------------------FN_DYNVARS_183_03------------------------#' +SET @@global.ndb_recv_thread_cpu_mask = '0,1,2,3-5,6-8,9'; +SELECT @@global.ndb_recv_thread_cpu_mask; +@@global.ndb_recv_thread_cpu_mask + +SET @@global.ndb_recv_thread_cpu_mask = '9'; +SELECT @@global.ndb_recv_thread_cpu_mask; +@@global.ndb_recv_thread_cpu_mask + +SET @@global.ndb_recv_thread_cpu_mask = '0,1,2'; +SELECT @@global.ndb_recv_thread_cpu_mask; +@@global.ndb_recv_thread_cpu_mask + +SET @@global.ndb_recv_thread_cpu_mask = '0,1,2,3-5,9'; +SELECT @@global.ndb_recv_thread_cpu_mask; +@@global.ndb_recv_thread_cpu_mask + +'#--------------------FN_DYNVARS_183_04-------------------------#' +SET @@global.ndb_recv_thread_cpu_mask = -1; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +SET @@global.ndb_recv_thread_cpu_mask = READUNCOMMITTED; +ERROR 42000: Variable 'ndb_recv_thread_cpu_mask' can't be set to the value of 'READUNCOMMITTED' +SET @@global.ndb_recv_thread_cpu_mask = 'REPEATABLE'; +ERROR 42000: Variable 'ndb_recv_thread_cpu_mask' can't be set to the value of 'REPEATABLE' +SET @@global.ndb_recv_thread_cpu_mask = OFF; +ERROR 42000: Variable 'ndb_recv_thread_cpu_mask' can't be set to the value of 'OFF' +SET @@global.ndb_recv_thread_cpu_mask = ON; +ERROR 42000: Variable 'ndb_recv_thread_cpu_mask' can't be set to the value of 'ON' +SET @@global.ndb_recv_thread_cpu_mask = 'NON-SERIALIZABLE'; +ERROR 42000: Variable 'ndb_recv_thread_cpu_mask' can't be set to the value of 'NON-SERIALIZABLE' +'#----------------------FN_DYNVARS_183_06------------------------#' +SELECT @@global.ndb_recv_thread_cpu_mask = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='ndb_recv_thread_cpu_mask'; +@@global.ndb_recv_thread_cpu_mask = VARIABLE_VALUE +1 +'#---------------------FN_DYNVARS_183_07-------------------------#' +SET @@global.ndb_recv_thread_cpu_mask = 0; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +SET @@global.ndb_recv_thread_cpu_mask = 1; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +SET @@global.ndb_recv_thread_cpu_mask = 2; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +SET @@global.ndb_recv_thread_cpu_mask = 3; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +SET @@global.ndb_recv_thread_cpu_mask = 0.4; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +'#---------------------FN_DYNVARS_183_08----------------------#' +SET @@global.ndb_recv_thread_cpu_mask = TRUE; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +SET @@global.ndb_recv_thread_cpu_mask = FALSE; +ERROR 42000: Incorrect argument type to variable 'ndb_recv_thread_cpu_mask' +'#---------------------FN_DYNVARS_183_09----------------------#' +SET ndb_recv_thread_cpu_mask = '1,2'; +ERROR HY000: Variable 'ndb_recv_thread_cpu_mask' is a GLOBAL variable and should be set with SET GLOBAL +SET global.ndb_recv_thread_cpu_mask = '1,3'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ndb_recv_thread_cpu_mask = '1,3'' at line 1 +SET session ndb_recv_thread_cpu_mask = '1,4'; +ERROR HY000: Variable 'ndb_recv_thread_cpu_mask' is a GLOBAL variable and should be set with SET GLOBAL +SET global ndb_recv_thread_cpu_mask = '1,5'; +SELECT @@global.ndb_recv_thread_cpu_mask; +@@global.ndb_recv_thread_cpu_mask + +SET @@global.ndb_recv_thread_cpu_mask = @global_start_value; +SELECT @@global.ndb_recv_thread_cpu_mask; +@@global.ndb_recv_thread_cpu_mask + === added file 'mysql-test/suite/ndb/t/ndb_recv_thread_cpu_mask_basic.test' --- a/mysql-test/suite/ndb/t/ndb_recv_thread_cpu_mask_basic.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/t/ndb_recv_thread_cpu_mask_basic.test revid:mikael.ronstrom@stripped @@ -0,0 +1,163 @@ +######## mysql-test\suite\ndb\t\ndb_recv_thread_cpu_mask_basic.test ########### +# # +# Variable Name: ndb_recv_thread_cpu_mask_basic # +# Scope: GLOBAL # +# Access Type: Dynamic # +# Data Type: string # +# Default Value: empty string # +# Valid Values: Comma separated lists of digits or ranges specified as # +# digit - digit, so e.g. 0,1,2-4,5,7-9 is a valid syntax # +# # +# # +# Creation Date: 2012-09-11 # +# Author: Mikael Ronstrom # +# # +# Description: Test Cases of Dynamic System Variable ndb_recv_thread_cpu_mask # +# that checks the behavior of this variable in the following ways# +# * Default Value # +# * Valid & Invalid values # +# * Scope & Access method # +# * Data Integrity # +# # +# Reference: http://dev.mysql.com/doc/refman/5.5/en/ # +# mysql-cluster-params-overview.html +# # +############################################################################### + +--source include/load_sysvars.inc + +######################################################################## +# START OF ndb_recv_thread_cpu_mask TESTS # +######################################################################## + + +############################################################################## +# Saving initial value of ndb_recv_thread_cpu_mask in a temporary variable # +############################################################################## + +SET @global_start_value = @@global.ndb_recv_thread_cpu_mask; +SELECT @global_start_value; + +--echo '#--------------------FN_DYNVARS_183_01------------------------#' +#################################################################### +# Display the DEFAULT value of tx_isolation # +#################################################################### + +SET @@global.ndb_recv_thread_cpu_mask = '1'; +SET @@global.ndb_recv_thread_cpu_mask = DEFAULT; +SELECT @@global.ndb_recv_thread_cpu_mask; + +--echo '#---------------------FN_DYNVARS_183_02-------------------------#' +######################################################### +# Check if NULL or empty value is accepted # +######################################################### + +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = NULL; + +SET @@global.ndb_recv_thread_cpu_mask = ''; + +--echo '#--------------------FN_DYNVARS_183_03------------------------#' +##################################################################### +# Change the value of ndb_recv_thread_cpu_mask to a valid value # +##################################################################### + +SET @@global.ndb_recv_thread_cpu_mask = '0,1,2,3-5,6-8,9'; +SELECT @@global.ndb_recv_thread_cpu_mask; + +SET @@global.ndb_recv_thread_cpu_mask = '9'; +SELECT @@global.ndb_recv_thread_cpu_mask; + +SET @@global.ndb_recv_thread_cpu_mask = '0,1,2'; +SELECT @@global.ndb_recv_thread_cpu_mask; + +SET @@global.ndb_recv_thread_cpu_mask = '0,1,2,3-5,9'; +SELECT @@global.ndb_recv_thread_cpu_mask; + +--echo '#--------------------FN_DYNVARS_183_04-------------------------#' +####################################################################### +# Change the value of tx_isolation to invalid value # +####################################################################### + +# for global scope +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = -1; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = READUNCOMMITTED; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = 'REPEATABLE'; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = OFF; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = ON; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = 'NON-SERIALIZABLE'; + +--echo '#----------------------FN_DYNVARS_183_06------------------------#' +######################################################################### +# Check if the value in GLOBAL Table matches value in variable # +######################################################################### + +SELECT @@global.ndb_recv_thread_cpu_mask = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='ndb_recv_thread_cpu_mask'; + +--echo '#---------------------FN_DYNVARS_183_07-------------------------#' +################################################################### +# Check if numbers can be used on variable # +################################################################### + +# test if variable accepts 0,1,2 +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = 0; + +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = 1; + +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = 2; + +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = 3; + +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = 0.4; + +--echo '#---------------------FN_DYNVARS_183_08----------------------#' +################################################################### +# Check if TRUE and FALSE values can be used on variable # +################################################################### + +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = TRUE; +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.ndb_recv_thread_cpu_mask = FALSE; + +--echo '#---------------------FN_DYNVARS_183_09----------------------#' +######################################################################## +# Check if tx_isolation can be accessed with and without @@ sign # +######################################################################## + +--Error ER_GLOBAL_VARIABLE +SET ndb_recv_thread_cpu_mask = '1,2'; + +--Error ER_PARSE_ERROR +SET global.ndb_recv_thread_cpu_mask = '1,3'; +#using SET SESSION|GLOBAL syntax +--Error ER_GLOBAL_VARIABLE +SET session ndb_recv_thread_cpu_mask = '1,4'; + +SET global ndb_recv_thread_cpu_mask = '1,5'; +SELECT @@global.ndb_recv_thread_cpu_mask; + +############################## +# Restore initial value # +############################## + +SET @@global.ndb_recv_thread_cpu_mask = @global_start_value; +SELECT @@global.ndb_recv_thread_cpu_mask; + +#################################################################### +# END OF ndb_recv_thread_cpu_mask TESTS # +#################################################################### + === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc revid:mikael.ronstrom@stripped +++ b/sql/ha_ndbcluster.cc revid:mikael.ronstrom@stripped @@ -1,4 +1,4 @@ -/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,6 +59,8 @@ #include "ndb_util_thread.h" #include "ndb_local_connection.h" #include "ndb_local_schema.h" +#include "../storage/ndb/src/common/util/parse_mask.hpp" +#include "../storage/ndb/include/util/SparseBitmask.hpp" // ndb interface initialization/cleanup extern "C" void ndb_init_internal(); @@ -11863,6 +11865,9 @@ static MYSQL_SYSVAR_STR( extern int ndb_dictionary_is_mysqld; +static int ndb_recv_thread_cpu_mask_check_str(const char *str); +static void ndb_recv_thread_cpu_mask_update(); + static int ndbcluster_init(void *p) { DBUG_ENTER("ndbcluster_init"); @@ -11921,6 +11926,12 @@ static int ndbcluster_init(void *p) // Initialize ndb interface ndb_init_internal(); + /* Translate recv thread cpu mask if set */ + if (ndb_recv_thread_cpu_mask_check_str(opt_ndb_recv_thread_cpu_mask) == 0) + { + ndb_recv_thread_cpu_mask_update(); + } + /* allocate connection resources and connect to cluster */ const uint global_opti_node_select= THDVAR(NULL, optimized_node_selection); if (ndbcluster_connect(connect_callback, opt_ndb_wait_connected, @@ -17141,81 +17152,13 @@ static MYSQL_SYSVAR_UINT( 0 /* block */ ); + +/* Definitions needed for receive thread cpu mask config variable */ static const int ndb_recv_thread_cpu_mask_option_buf_size = 512; char ndb_recv_thread_cpu_mask_option_buf[ndb_recv_thread_cpu_mask_option_buf_size]; Uint16 recv_thread_cpuid_array[MAX_NUM_RECV_THREADS * MAX_CLUSTER_CONNECTIONS]; Uint32 recv_thread_num_cpus; -static int -count_bits_in_hex_number(Uint32 hex_number) -{ - int num_cpus = 0; - for (int i = 0; i < 4; i++) - { - if (hex_number & (1 << i)) - { - num_cpus++; - } - } - return num_cpus; -} - -static int -assign_cpuid_in_array_from_hexnumber(Uint32 hex_number, Uint32 base_cpuid) -{ - if ((recv_thread_num_cpus + count_bits_in_hex_number(hex_number)) >= - (MAX_NUM_RECV_THREADS * MAX_CLUSTER_CONNECTIONS)) - { - return -1; - } - for (int i = 0; i < 4; i++) - { - if (hex_number & (1 << i)) - { - recv_thread_cpuid_array[recv_thread_num_cpus++] = (base_cpuid + i); - } - } - return 0; -} - -static int -assign_cpus_from_character(char c, Uint32 base_cpuid) -{ - Uint32 hex_number; - - if (c >= '0' && c <= '9') - hex_number = (c - '0'); - else if (c >= 'A' && c <= 'F') - hex_number = (c - 'A') + 10; - else if (c >= 'a' && c <= 'f') - hex_number = (c - 'a') + 10; - else - return -1; - return assign_cpuid_in_array_from_hexnumber(hex_number, base_cpuid); -} - -static int -cpu_mask_parse(const char *str, int mask_str_len) -{ - Uint32 base_cpu_id = 0; - recv_thread_num_cpus = 0; - if (str[0] != '0' || str[1] != 'x') - goto error; - for (int i = mask_str_len - 1; i >= 2; i++) - { - /* - Parse string backwards, last character is representing - CPU 0-3, next to last represents 4-7 and so forth. - */ - if (assign_cpus_from_character(str[i], base_cpu_id) != 0) - goto error; - base_cpu_id += 4; - } - return 0; -error: - return -1; -} - static int ndb_recv_thread_cpu_mask_check(MYSQL_THD thd, @@ -17223,16 +17166,44 @@ ndb_recv_thread_cpu_mask_check(MYSQL_THD void *save, struct st_mysql_value *value) { - int mask_str_len; char buf[ndb_recv_thread_cpu_mask_option_buf_size]; int len = sizeof(buf); const char *str = value->val_str(value, buf, &len); - if (str != 0) + + return ndb_recv_thread_cpu_mask_check_str(str); +} + +static int +ndb_recv_thread_cpu_mask_check_str(const char *str) +{ + unsigned i; + SparseBitmask bitmask; + + recv_thread_num_cpus = 0; + if (str == 0) + goto error; + + if (parse_mask(str, bitmask) < 0) { - mask_str_len = strlen(str); - if ((mask_str_len >= len) || - (cpu_mask_parse(str, mask_str_len) != 0)) + sql_print_information("Trying to set ndb_recv_thread_cpu_mask to" + " illegal value = %s, ignored", + str); + goto error; + } + for (i = bitmask.find(0); + i != SparseBitmask::NotFound; + i = bitmask.find(i + 1)) + { + if (recv_thread_num_cpus == + MAX_NUM_RECV_THREADS * MAX_CLUSTER_CONNECTIONS) + { + sql_print_information("Trying to set too many CPU's in " + "ndb_recv_thread_cpu_mask, ignored" + " this variable, erroneus value = %s", + str); goto error; + } + recv_thread_cpuid_array[recv_thread_num_cpus++] = i; } return 0; error: @@ -17241,16 +17212,23 @@ error: static void -ndb_recv_thread_cpu_mask_update(MYSQL_THD, - struct st_mysql_sys_var *var, - void *var_ptr, - const void *save) +ndb_recv_thread_cpu_mask_update(void) { ndb_set_recv_thread_cpu(recv_thread_cpuid_array, opt_ndb_num_recv_threads, recv_thread_num_cpus); } +static +void +ndb_recv_thread_cpu_mask_update_func(MYSQL_THD, + struct st_mysql_sys_var *var, + void *var_ptr, + const void *save) +{ + ndb_recv_thread_cpu_mask_update(); +} + static MYSQL_SYSVAR_STR( recv_thread_cpu_mask, /* name */ opt_ndb_recv_thread_cpu_mask, /* var */ @@ -17258,7 +17236,7 @@ static MYSQL_SYSVAR_STR( "CPU mask for locking receiver threads to specific CPU, specified " " as hexadecimal as e.g. 0x33, one CPU is used per receiver thread.", ndb_recv_thread_cpu_mask_check, /* check func. */ - ndb_recv_thread_cpu_mask_update, /* update func. */ + ndb_recv_thread_cpu_mask_update_func,/* update func. */ ndb_recv_thread_cpu_mask_option_buf ); === modified file 'storage/ndb/src/common/portlib/NdbThread.c' --- a/storage/ndb/src/common/portlib/NdbThread.c revid:mikael.ronstrom@stripped +++ b/storage/ndb/src/common/portlib/NdbThread.c revid:mikael.ronstrom@stripped @@ -69,6 +69,7 @@ struct NdbThread char thread_name[16]; NDB_THREAD_FUNC * func; void * object; + void *thread_key; #ifdef NDB_MUTEX_DEADLOCK_DETECTOR struct ndb_mutex_thr_state m_mutex_thr_state; #endif @@ -172,7 +173,7 @@ struct NdbThread* NdbThread_CreateObject(const char * name) { struct NdbThread* tmpThread; - DBUG_ENTER("NdbThread_Create"); + DBUG_ENTER("NdbThread_CreateObject"); if (g_main_thread != 0) { @@ -269,6 +270,7 @@ NdbThread_Create(NDB_THREAD_FUNC *p_thre tmpThread->inited = 0; tmpThread->func= p_thread_func; tmpThread->object= p_thread_arg; + tmpThread->thread_key = NULL; NdbMutex_Lock(g_ndb_thread_mutex); result = pthread_create(&tmpThread->thread, @@ -313,6 +315,13 @@ void NdbThread_Destroy(struct NdbThread* DBUG_ENTER("NdbThread_Destroy"); if (*p_thread != NULL){ DBUG_PRINT("enter",("*p_thread: 0x%lx", (long) *p_thread)); +#ifdef HAVE_LINUX_SCHEDULING + if ((*p_thread)->thread_key) + { + free((*p_thread)->thread_key); + (*p_thread)->thread_key = NULL; + } +#endif free(* p_thread); * p_thread = 0; } @@ -463,6 +472,32 @@ NdbThread_SetScheduler(struct NdbThread* } int +NdbThread_UnlockCPU(struct NdbThread* pThread) +{ + int ret; + int error_no = 0; + if (pThread->thread_key != NULL) + { +#if defined HAVE_LINUX_SCHEDULING + cpu_set_t *cpu_set_ptr = (cpu_set_t *)pThread->thread_key; + ret= sched_setaffinity(pThread->tid, sizeof(cpu_set_t), cpu_set_ptr); + if (ret) + { + error_no = errno; + } +#elif defined HAVE_SOLARIS_AFFINITY + processorid_t *cpu_id = (processorid_t*)pThread->thread_key; + ret= processor_bind(P_LWPID, pThread->tid, *cpu_id, NULL); + if (ret) + { + error_no = errno; + } +#endif + } + return error_no; +} + +int NdbThread_LockCPU(struct NdbThread* pThread, Uint32 cpu_id) { int error_no = 0; @@ -480,11 +515,25 @@ NdbThread_LockCPU(struct NdbThread* pThr */ int ret; cpu_set_t cpu_set; + + if (pThread->thread_key == NULL) + { + cpu_set_t *old_cpu_set_ptr = malloc(sizeof(cpu_set)); + ret = sched_getaffinity(pThread->tid, sizeof(cpu_set), old_cpu_set_ptr); + if (ret) + { + error_no = errno; + goto end; + } + pThread->thread_key = (void*)old_cpu_set_ptr; + } CPU_ZERO(&cpu_set); CPU_SET(cpu_id, &cpu_set); ret= sched_setaffinity(pThread->tid, sizeof(cpu_set), &cpu_set); if (ret) + { error_no = errno; + } #elif defined HAVE_SOLARIS_AFFINITY /* Solaris have a number of versions to lock threads to CPU's. @@ -494,12 +543,25 @@ NdbThread_LockCPU(struct NdbThread* pThr is the LWP id. */ int ret; + if (pThread->thread_key == NULL) + { + processorid_t *old_cpu_id_ptr = malloc(sizeof(processorid_t)); + ret= processor_bind(P_LWPID, pThread->tid, PBIND_QUERY, old_cpu_id); + if (ret) + { + error_no= errno; + goto end; + } + pThread->thread_key = (void*)old_cpu_id_ptr; + } ret= processor_bind(P_LWPID, pThread->tid, cpu_id, NULL); if (ret) error_no= errno; #else error_no = ENOSYS; + goto end; #endif +end: return error_no; } No bundle (reason: useless for push emails).