mttest.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310
  1. /* crypto/threads/mttest.c */
  2. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  3. * All rights reserved.
  4. *
  5. * This package is an SSL implementation written
  6. * by Eric Young (eay@cryptsoft.com).
  7. * The implementation was written so as to conform with Netscapes SSL.
  8. *
  9. * This library is free for commercial and non-commercial use as long as
  10. * the following conditions are aheared to. The following conditions
  11. * apply to all code found in this distribution, be it the RC4, RSA,
  12. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  13. * included with this distribution is covered by the same copyright terms
  14. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15. *
  16. * Copyright remains Eric Young's, and as such any Copyright notices in
  17. * the code are not to be removed.
  18. * If this package is used in a product, Eric Young should be given attribution
  19. * as the author of the parts of the library used.
  20. * This can be in the form of a textual message at program startup or
  21. * in documentation (online or textual) provided with the package.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. * 3. All advertising materials mentioning features or use of this software
  32. * must display the following acknowledgement:
  33. * "This product includes cryptographic software written by
  34. * Eric Young (eay@cryptsoft.com)"
  35. * The word 'cryptographic' can be left out if the rouines from the library
  36. * being used are not cryptographic related :-).
  37. * 4. If you include any Windows specific code (or a derivative thereof) from
  38. * the apps directory (application code) you must include an acknowledgement:
  39. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51. * SUCH DAMAGE.
  52. *
  53. * The licence and distribution terms for any publically available version or
  54. * derivative of this code cannot be changed. i.e. this code cannot simply be
  55. * copied and put under another distribution licence
  56. * [including the GNU Public Licence.]
  57. */
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <errno.h>
  62. #ifdef LINUX
  63. #include <typedefs.h>
  64. #endif
  65. #ifdef OPENSSL_SYS_WIN32
  66. #include <windows.h>
  67. #endif
  68. #ifdef SOLARIS
  69. #include <synch.h>
  70. #include <thread.h>
  71. #endif
  72. #ifdef IRIX
  73. #include <ulocks.h>
  74. #include <sys/prctl.h>
  75. #endif
  76. #ifdef PTHREADS
  77. #include <pthread.h>
  78. #endif
  79. #ifdef OPENSSL_SYS_NETWARE
  80. #if !defined __int64
  81. # define __int64 long long
  82. #endif
  83. #include <nwmpk.h>
  84. #endif
  85. #include <openssl/lhash.h>
  86. #include <openssl/crypto.h>
  87. #include <openssl/buffer.h>
  88. #include "../../e_os.h"
  89. #include <openssl/x509.h>
  90. #include <openssl/ssl.h>
  91. #include <openssl/err.h>
  92. #include <openssl/rand.h>
  93. #ifdef OPENSSL_NO_FP_API
  94. #define APPS_WIN16
  95. #include "../buffer/bss_file.c"
  96. #endif
  97. #ifdef OPENSSL_SYS_NETWARE
  98. #define TEST_SERVER_CERT "/openssl/apps/server.pem"
  99. #define TEST_CLIENT_CERT "/openssl/apps/client.pem"
  100. #else
  101. #define TEST_SERVER_CERT "../../apps/server.pem"
  102. #define TEST_CLIENT_CERT "../../apps/client.pem"
  103. #endif
  104. #define MAX_THREAD_NUMBER 100
  105. int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *xs);
  106. void thread_setup(void);
  107. void thread_cleanup(void);
  108. void do_threads(SSL_CTX *s_ctx,SSL_CTX *c_ctx);
  109. void irix_locking_callback(int mode,int type,char *file,int line);
  110. void solaris_locking_callback(int mode,int type,char *file,int line);
  111. void win32_locking_callback(int mode,int type,char *file,int line);
  112. void pthreads_locking_callback(int mode,int type,char *file,int line);
  113. void netware_locking_callback(int mode,int type,char *file,int line);
  114. void beos_locking_callback(int mode,int type,const char *file,int line);
  115. unsigned long irix_thread_id(void );
  116. unsigned long solaris_thread_id(void );
  117. unsigned long pthreads_thread_id(void );
  118. unsigned long netware_thread_id(void );
  119. unsigned long beos_thread_id(void );
  120. #if defined(OPENSSL_SYS_NETWARE)
  121. static MPKMutex *lock_cs;
  122. static MPKSema ThreadSem;
  123. static long *lock_count;
  124. #endif
  125. BIO *bio_err=NULL;
  126. BIO *bio_stdout=NULL;
  127. static char *cipher=NULL;
  128. int verbose=0;
  129. #ifdef FIONBIO
  130. static int s_nbio=0;
  131. #endif
  132. int thread_number=10;
  133. int number_of_loops=10;
  134. int reconnect=0;
  135. int cache_stats=0;
  136. static const char rnd_seed[] = "string to make the random number generator think it has entropy";
  137. int doit(char *ctx[4]);
  138. static void print_stats(FILE *fp, SSL_CTX *ctx)
  139. {
  140. fprintf(fp,"%4ld items in the session cache\n",
  141. SSL_CTX_sess_number(ctx));
  142. fprintf(fp,"%4d client connects (SSL_connect())\n",
  143. SSL_CTX_sess_connect(ctx));
  144. fprintf(fp,"%4d client connects that finished\n",
  145. SSL_CTX_sess_connect_good(ctx));
  146. fprintf(fp,"%4d server connects (SSL_accept())\n",
  147. SSL_CTX_sess_accept(ctx));
  148. fprintf(fp,"%4d server connects that finished\n",
  149. SSL_CTX_sess_accept_good(ctx));
  150. fprintf(fp,"%4d session cache hits\n",SSL_CTX_sess_hits(ctx));
  151. fprintf(fp,"%4d session cache misses\n",SSL_CTX_sess_misses(ctx));
  152. fprintf(fp,"%4d session cache timeouts\n",SSL_CTX_sess_timeouts(ctx));
  153. }
  154. static void sv_usage(void)
  155. {
  156. fprintf(stderr,"usage: ssltest [args ...]\n");
  157. fprintf(stderr,"\n");
  158. fprintf(stderr," -server_auth - check server certificate\n");
  159. fprintf(stderr," -client_auth - do client authentication\n");
  160. fprintf(stderr," -v - more output\n");
  161. fprintf(stderr," -CApath arg - PEM format directory of CA's\n");
  162. fprintf(stderr," -CAfile arg - PEM format file of CA's\n");
  163. fprintf(stderr," -threads arg - number of threads\n");
  164. fprintf(stderr," -loops arg - number of 'connections', per thread\n");
  165. fprintf(stderr," -reconnect - reuse session-id's\n");
  166. fprintf(stderr," -stats - server session-id cache stats\n");
  167. fprintf(stderr," -cert arg - server certificate/key\n");
  168. fprintf(stderr," -ccert arg - client certificate/key\n");
  169. fprintf(stderr," -ssl3 - just SSLv3n\n");
  170. }
  171. int main(int argc, char *argv[])
  172. {
  173. char *CApath=NULL,*CAfile=NULL;
  174. int badop=0;
  175. int ret=1;
  176. int client_auth=0;
  177. int server_auth=0;
  178. SSL_CTX *s_ctx=NULL;
  179. SSL_CTX *c_ctx=NULL;
  180. char *scert=TEST_SERVER_CERT;
  181. char *ccert=TEST_CLIENT_CERT;
  182. SSL_METHOD *ssl_method=SSLv23_method();
  183. RAND_seed(rnd_seed, sizeof rnd_seed);
  184. if (bio_err == NULL)
  185. bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
  186. if (bio_stdout == NULL)
  187. bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
  188. argc--;
  189. argv++;
  190. while (argc >= 1)
  191. {
  192. if (strcmp(*argv,"-server_auth") == 0)
  193. server_auth=1;
  194. else if (strcmp(*argv,"-client_auth") == 0)
  195. client_auth=1;
  196. else if (strcmp(*argv,"-reconnect") == 0)
  197. reconnect=1;
  198. else if (strcmp(*argv,"-stats") == 0)
  199. cache_stats=1;
  200. else if (strcmp(*argv,"-ssl3") == 0)
  201. ssl_method=SSLv3_method();
  202. else if (strcmp(*argv,"-ssl2") == 0)
  203. ssl_method=SSLv2_method();
  204. else if (strcmp(*argv,"-CApath") == 0)
  205. {
  206. if (--argc < 1) goto bad;
  207. CApath= *(++argv);
  208. }
  209. else if (strcmp(*argv,"-CAfile") == 0)
  210. {
  211. if (--argc < 1) goto bad;
  212. CAfile= *(++argv);
  213. }
  214. else if (strcmp(*argv,"-cert") == 0)
  215. {
  216. if (--argc < 1) goto bad;
  217. scert= *(++argv);
  218. }
  219. else if (strcmp(*argv,"-ccert") == 0)
  220. {
  221. if (--argc < 1) goto bad;
  222. ccert= *(++argv);
  223. }
  224. else if (strcmp(*argv,"-threads") == 0)
  225. {
  226. if (--argc < 1) goto bad;
  227. thread_number= atoi(*(++argv));
  228. if (thread_number == 0) thread_number=1;
  229. if (thread_number > MAX_THREAD_NUMBER)
  230. thread_number=MAX_THREAD_NUMBER;
  231. }
  232. else if (strcmp(*argv,"-loops") == 0)
  233. {
  234. if (--argc < 1) goto bad;
  235. number_of_loops= atoi(*(++argv));
  236. if (number_of_loops == 0) number_of_loops=1;
  237. }
  238. else
  239. {
  240. fprintf(stderr,"unknown option %s\n",*argv);
  241. badop=1;
  242. break;
  243. }
  244. argc--;
  245. argv++;
  246. }
  247. if (badop)
  248. {
  249. bad:
  250. sv_usage();
  251. goto end;
  252. }
  253. if (cipher == NULL && OPENSSL_issetugid() == 0)
  254. cipher=getenv("SSL_CIPHER");
  255. SSL_load_error_strings();
  256. OpenSSL_add_ssl_algorithms();
  257. c_ctx=SSL_CTX_new(ssl_method);
  258. s_ctx=SSL_CTX_new(ssl_method);
  259. if ((c_ctx == NULL) || (s_ctx == NULL))
  260. {
  261. ERR_print_errors(bio_err);
  262. goto end;
  263. }
  264. SSL_CTX_set_session_cache_mode(s_ctx,
  265. SSL_SESS_CACHE_NO_AUTO_CLEAR|SSL_SESS_CACHE_SERVER);
  266. SSL_CTX_set_session_cache_mode(c_ctx,
  267. SSL_SESS_CACHE_NO_AUTO_CLEAR|SSL_SESS_CACHE_SERVER);
  268. if (!SSL_CTX_use_certificate_file(s_ctx,scert,SSL_FILETYPE_PEM))
  269. {
  270. ERR_print_errors(bio_err);
  271. }
  272. else if (!SSL_CTX_use_RSAPrivateKey_file(s_ctx,scert,SSL_FILETYPE_PEM))
  273. {
  274. ERR_print_errors(bio_err);
  275. goto end;
  276. }
  277. if (client_auth)
  278. {
  279. SSL_CTX_use_certificate_file(c_ctx,ccert,
  280. SSL_FILETYPE_PEM);
  281. SSL_CTX_use_RSAPrivateKey_file(c_ctx,ccert,
  282. SSL_FILETYPE_PEM);
  283. }
  284. if ( (!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
  285. (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
  286. (!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
  287. (!SSL_CTX_set_default_verify_paths(c_ctx)))
  288. {
  289. fprintf(stderr,"SSL_load_verify_locations\n");
  290. ERR_print_errors(bio_err);
  291. goto end;
  292. }
  293. if (client_auth)
  294. {
  295. fprintf(stderr,"client authentication\n");
  296. SSL_CTX_set_verify(s_ctx,
  297. SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
  298. verify_callback);
  299. }
  300. if (server_auth)
  301. {
  302. fprintf(stderr,"server authentication\n");
  303. SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
  304. verify_callback);
  305. }
  306. thread_setup();
  307. do_threads(s_ctx,c_ctx);
  308. thread_cleanup();
  309. end:
  310. if (c_ctx != NULL)
  311. {
  312. fprintf(stderr,"Client SSL_CTX stats then free it\n");
  313. print_stats(stderr,c_ctx);
  314. SSL_CTX_free(c_ctx);
  315. }
  316. if (s_ctx != NULL)
  317. {
  318. fprintf(stderr,"Server SSL_CTX stats then free it\n");
  319. print_stats(stderr,s_ctx);
  320. if (cache_stats)
  321. {
  322. fprintf(stderr,"-----\n");
  323. lh_stats(SSL_CTX_sessions(s_ctx),stderr);
  324. fprintf(stderr,"-----\n");
  325. /* lh_node_stats(SSL_CTX_sessions(s_ctx),stderr);
  326. fprintf(stderr,"-----\n"); */
  327. lh_node_usage_stats(SSL_CTX_sessions(s_ctx),stderr);
  328. fprintf(stderr,"-----\n");
  329. }
  330. SSL_CTX_free(s_ctx);
  331. fprintf(stderr,"done free\n");
  332. }
  333. exit(ret);
  334. return(0);
  335. }
  336. #define W_READ 1
  337. #define W_WRITE 2
  338. #define C_DONE 1
  339. #define S_DONE 2
  340. int ndoit(SSL_CTX *ssl_ctx[2])
  341. {
  342. int i;
  343. int ret;
  344. char *ctx[4];
  345. ctx[0]=(char *)ssl_ctx[0];
  346. ctx[1]=(char *)ssl_ctx[1];
  347. if (reconnect)
  348. {
  349. ctx[2]=(char *)SSL_new(ssl_ctx[0]);
  350. ctx[3]=(char *)SSL_new(ssl_ctx[1]);
  351. }
  352. else
  353. {
  354. ctx[2]=NULL;
  355. ctx[3]=NULL;
  356. }
  357. fprintf(stdout,"started thread %lu\n",CRYPTO_thread_id());
  358. for (i=0; i<number_of_loops; i++)
  359. {
  360. /* fprintf(stderr,"%4d %2d ctx->ref (%3d,%3d)\n",
  361. CRYPTO_thread_id(),i,
  362. ssl_ctx[0]->references,
  363. ssl_ctx[1]->references); */
  364. /* pthread_delay_np(&tm);*/
  365. ret=doit(ctx);
  366. if (ret != 0)
  367. {
  368. fprintf(stdout,"error[%d] %lu - %d\n",
  369. i,CRYPTO_thread_id(),ret);
  370. return(ret);
  371. }
  372. }
  373. fprintf(stdout,"DONE %lu\n",CRYPTO_thread_id());
  374. if (reconnect)
  375. {
  376. SSL_free((SSL *)ctx[2]);
  377. SSL_free((SSL *)ctx[3]);
  378. }
  379. # ifdef OPENSSL_SYS_NETWARE
  380. MPKSemaphoreSignal(ThreadSem);
  381. # endif
  382. return(0);
  383. }
  384. int doit(char *ctx[4])
  385. {
  386. SSL_CTX *s_ctx,*c_ctx;
  387. static char cbuf[200],sbuf[200];
  388. SSL *c_ssl=NULL;
  389. SSL *s_ssl=NULL;
  390. BIO *c_to_s=NULL;
  391. BIO *s_to_c=NULL;
  392. BIO *c_bio=NULL;
  393. BIO *s_bio=NULL;
  394. int c_r,c_w,s_r,s_w;
  395. int c_want,s_want;
  396. int i;
  397. int done=0;
  398. int c_write,s_write;
  399. int do_server=0,do_client=0;
  400. s_ctx=(SSL_CTX *)ctx[0];
  401. c_ctx=(SSL_CTX *)ctx[1];
  402. if (ctx[2] != NULL)
  403. s_ssl=(SSL *)ctx[2];
  404. else
  405. s_ssl=SSL_new(s_ctx);
  406. if (ctx[3] != NULL)
  407. c_ssl=(SSL *)ctx[3];
  408. else
  409. c_ssl=SSL_new(c_ctx);
  410. if ((s_ssl == NULL) || (c_ssl == NULL)) goto err;
  411. c_to_s=BIO_new(BIO_s_mem());
  412. s_to_c=BIO_new(BIO_s_mem());
  413. if ((s_to_c == NULL) || (c_to_s == NULL)) goto err;
  414. c_bio=BIO_new(BIO_f_ssl());
  415. s_bio=BIO_new(BIO_f_ssl());
  416. if ((c_bio == NULL) || (s_bio == NULL)) goto err;
  417. SSL_set_connect_state(c_ssl);
  418. SSL_set_bio(c_ssl,s_to_c,c_to_s);
  419. BIO_set_ssl(c_bio,c_ssl,(ctx[2] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
  420. SSL_set_accept_state(s_ssl);
  421. SSL_set_bio(s_ssl,c_to_s,s_to_c);
  422. BIO_set_ssl(s_bio,s_ssl,(ctx[3] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
  423. c_r=0; s_r=1;
  424. c_w=1; s_w=0;
  425. c_want=W_WRITE;
  426. s_want=0;
  427. c_write=1,s_write=0;
  428. /* We can always do writes */
  429. for (;;)
  430. {
  431. do_server=0;
  432. do_client=0;
  433. i=(int)BIO_pending(s_bio);
  434. if ((i && s_r) || s_w) do_server=1;
  435. i=(int)BIO_pending(c_bio);
  436. if ((i && c_r) || c_w) do_client=1;
  437. if (do_server && verbose)
  438. {
  439. if (SSL_in_init(s_ssl))
  440. printf("server waiting in SSL_accept - %s\n",
  441. SSL_state_string_long(s_ssl));
  442. else if (s_write)
  443. printf("server:SSL_write()\n");
  444. else
  445. printf("server:SSL_read()\n");
  446. }
  447. if (do_client && verbose)
  448. {
  449. if (SSL_in_init(c_ssl))
  450. printf("client waiting in SSL_connect - %s\n",
  451. SSL_state_string_long(c_ssl));
  452. else if (c_write)
  453. printf("client:SSL_write()\n");
  454. else
  455. printf("client:SSL_read()\n");
  456. }
  457. if (!do_client && !do_server)
  458. {
  459. fprintf(stdout,"ERROR IN STARTUP\n");
  460. break;
  461. }
  462. if (do_client && !(done & C_DONE))
  463. {
  464. if (c_write)
  465. {
  466. i=BIO_write(c_bio,"hello from client\n",18);
  467. if (i < 0)
  468. {
  469. c_r=0;
  470. c_w=0;
  471. if (BIO_should_retry(c_bio))
  472. {
  473. if (BIO_should_read(c_bio))
  474. c_r=1;
  475. if (BIO_should_write(c_bio))
  476. c_w=1;
  477. }
  478. else
  479. {
  480. fprintf(stderr,"ERROR in CLIENT\n");
  481. ERR_print_errors_fp(stderr);
  482. return(1);
  483. }
  484. }
  485. else if (i == 0)
  486. {
  487. fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
  488. return(1);
  489. }
  490. else
  491. {
  492. /* ok */
  493. c_write=0;
  494. }
  495. }
  496. else
  497. {
  498. i=BIO_read(c_bio,cbuf,100);
  499. if (i < 0)
  500. {
  501. c_r=0;
  502. c_w=0;
  503. if (BIO_should_retry(c_bio))
  504. {
  505. if (BIO_should_read(c_bio))
  506. c_r=1;
  507. if (BIO_should_write(c_bio))
  508. c_w=1;
  509. }
  510. else
  511. {
  512. fprintf(stderr,"ERROR in CLIENT\n");
  513. ERR_print_errors_fp(stderr);
  514. return(1);
  515. }
  516. }
  517. else if (i == 0)
  518. {
  519. fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
  520. return(1);
  521. }
  522. else
  523. {
  524. done|=C_DONE;
  525. #ifdef undef
  526. fprintf(stdout,"CLIENT:from server:");
  527. fwrite(cbuf,1,i,stdout);
  528. fflush(stdout);
  529. #endif
  530. }
  531. }
  532. }
  533. if (do_server && !(done & S_DONE))
  534. {
  535. if (!s_write)
  536. {
  537. i=BIO_read(s_bio,sbuf,100);
  538. if (i < 0)
  539. {
  540. s_r=0;
  541. s_w=0;
  542. if (BIO_should_retry(s_bio))
  543. {
  544. if (BIO_should_read(s_bio))
  545. s_r=1;
  546. if (BIO_should_write(s_bio))
  547. s_w=1;
  548. }
  549. else
  550. {
  551. fprintf(stderr,"ERROR in SERVER\n");
  552. ERR_print_errors_fp(stderr);
  553. return(1);
  554. }
  555. }
  556. else if (i == 0)
  557. {
  558. fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
  559. return(1);
  560. }
  561. else
  562. {
  563. s_write=1;
  564. s_w=1;
  565. #ifdef undef
  566. fprintf(stdout,"SERVER:from client:");
  567. fwrite(sbuf,1,i,stdout);
  568. fflush(stdout);
  569. #endif
  570. }
  571. }
  572. else
  573. {
  574. i=BIO_write(s_bio,"hello from server\n",18);
  575. if (i < 0)
  576. {
  577. s_r=0;
  578. s_w=0;
  579. if (BIO_should_retry(s_bio))
  580. {
  581. if (BIO_should_read(s_bio))
  582. s_r=1;
  583. if (BIO_should_write(s_bio))
  584. s_w=1;
  585. }
  586. else
  587. {
  588. fprintf(stderr,"ERROR in SERVER\n");
  589. ERR_print_errors_fp(stderr);
  590. return(1);
  591. }
  592. }
  593. else if (i == 0)
  594. {
  595. fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
  596. return(1);
  597. }
  598. else
  599. {
  600. s_write=0;
  601. s_r=1;
  602. done|=S_DONE;
  603. }
  604. }
  605. }
  606. if ((done & S_DONE) && (done & C_DONE)) break;
  607. # if defined(OPENSSL_SYS_NETWARE)
  608. ThreadSwitchWithDelay();
  609. # endif
  610. }
  611. SSL_set_shutdown(c_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
  612. SSL_set_shutdown(s_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
  613. #ifdef undef
  614. fprintf(stdout,"DONE\n");
  615. #endif
  616. err:
  617. /* We have to set the BIO's to NULL otherwise they will be
  618. * free()ed twice. Once when th s_ssl is SSL_free()ed and
  619. * again when c_ssl is SSL_free()ed.
  620. * This is a hack required because s_ssl and c_ssl are sharing the same
  621. * BIO structure and SSL_set_bio() and SSL_free() automatically
  622. * BIO_free non NULL entries.
  623. * You should not normally do this or be required to do this */
  624. if (s_ssl != NULL)
  625. {
  626. s_ssl->rbio=NULL;
  627. s_ssl->wbio=NULL;
  628. }
  629. if (c_ssl != NULL)
  630. {
  631. c_ssl->rbio=NULL;
  632. c_ssl->wbio=NULL;
  633. }
  634. /* The SSL's are optionally freed in the following calls */
  635. if (c_to_s != NULL) BIO_free(c_to_s);
  636. if (s_to_c != NULL) BIO_free(s_to_c);
  637. if (c_bio != NULL) BIO_free(c_bio);
  638. if (s_bio != NULL) BIO_free(s_bio);
  639. return(0);
  640. }
  641. int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
  642. {
  643. char *s, buf[256];
  644. if (verbose)
  645. {
  646. s=X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),
  647. buf,256);
  648. if (s != NULL)
  649. {
  650. if (ok)
  651. fprintf(stderr,"depth=%d %s\n",
  652. ctx->error_depth,buf);
  653. else
  654. fprintf(stderr,"depth=%d error=%d %s\n",
  655. ctx->error_depth,ctx->error,buf);
  656. }
  657. }
  658. return(ok);
  659. }
  660. #define THREAD_STACK_SIZE (16*1024)
  661. #ifdef OPENSSL_SYS_WIN32
  662. static HANDLE *lock_cs;
  663. void thread_setup(void)
  664. {
  665. int i;
  666. lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
  667. for (i=0; i<CRYPTO_num_locks(); i++)
  668. {
  669. lock_cs[i]=CreateMutex(NULL,FALSE,NULL);
  670. }
  671. CRYPTO_set_locking_callback((void (*)(int,int,char *,int))win32_locking_callback);
  672. /* id callback defined */
  673. }
  674. void thread_cleanup(void)
  675. {
  676. int i;
  677. CRYPTO_set_locking_callback(NULL);
  678. for (i=0; i<CRYPTO_num_locks(); i++)
  679. CloseHandle(lock_cs[i]);
  680. OPENSSL_free(lock_cs);
  681. }
  682. void win32_locking_callback(int mode, int type, char *file, int line)
  683. {
  684. if (mode & CRYPTO_LOCK)
  685. {
  686. WaitForSingleObject(lock_cs[type],INFINITE);
  687. }
  688. else
  689. {
  690. ReleaseMutex(lock_cs[type]);
  691. }
  692. }
  693. void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
  694. {
  695. double ret;
  696. SSL_CTX *ssl_ctx[2];
  697. DWORD thread_id[MAX_THREAD_NUMBER];
  698. HANDLE thread_handle[MAX_THREAD_NUMBER];
  699. int i;
  700. SYSTEMTIME start,end;
  701. ssl_ctx[0]=s_ctx;
  702. ssl_ctx[1]=c_ctx;
  703. GetSystemTime(&start);
  704. for (i=0; i<thread_number; i++)
  705. {
  706. thread_handle[i]=CreateThread(NULL,
  707. THREAD_STACK_SIZE,
  708. (LPTHREAD_START_ROUTINE)ndoit,
  709. (void *)ssl_ctx,
  710. 0L,
  711. &(thread_id[i]));
  712. }
  713. printf("reaping\n");
  714. for (i=0; i<thread_number; i+=50)
  715. {
  716. int j;
  717. j=(thread_number < (i+50))?(thread_number-i):50;
  718. if (WaitForMultipleObjects(j,
  719. (CONST HANDLE *)&(thread_handle[i]),TRUE,INFINITE)
  720. == WAIT_FAILED)
  721. {
  722. fprintf(stderr,"WaitForMultipleObjects failed:%d\n",GetLastError());
  723. exit(1);
  724. }
  725. }
  726. GetSystemTime(&end);
  727. if (start.wDayOfWeek > end.wDayOfWeek) end.wDayOfWeek+=7;
  728. ret=(end.wDayOfWeek-start.wDayOfWeek)*24;
  729. ret=(ret+end.wHour-start.wHour)*60;
  730. ret=(ret+end.wMinute-start.wMinute)*60;
  731. ret=(ret+end.wSecond-start.wSecond);
  732. ret+=(end.wMilliseconds-start.wMilliseconds)/1000.0;
  733. printf("win32 threads done - %.3f seconds\n",ret);
  734. }
  735. #endif /* OPENSSL_SYS_WIN32 */
  736. #ifdef SOLARIS
  737. static mutex_t *lock_cs;
  738. /*static rwlock_t *lock_cs; */
  739. static long *lock_count;
  740. void thread_setup(void)
  741. {
  742. int i;
  743. lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t));
  744. lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
  745. for (i=0; i<CRYPTO_num_locks(); i++)
  746. {
  747. lock_count[i]=0;
  748. /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
  749. mutex_init(&(lock_cs[i]),USYNC_THREAD,NULL);
  750. }
  751. CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id);
  752. CRYPTO_set_locking_callback((void (*)())solaris_locking_callback);
  753. }
  754. void thread_cleanup(void)
  755. {
  756. int i;
  757. CRYPTO_set_locking_callback(NULL);
  758. fprintf(stderr,"cleanup\n");
  759. for (i=0; i<CRYPTO_num_locks(); i++)
  760. {
  761. /* rwlock_destroy(&(lock_cs[i])); */
  762. mutex_destroy(&(lock_cs[i]));
  763. fprintf(stderr,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
  764. }
  765. OPENSSL_free(lock_cs);
  766. OPENSSL_free(lock_count);
  767. fprintf(stderr,"done cleanup\n");
  768. }
  769. void solaris_locking_callback(int mode, int type, char *file, int line)
  770. {
  771. #ifdef undef
  772. fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
  773. CRYPTO_thread_id(),
  774. (mode&CRYPTO_LOCK)?"l":"u",
  775. (type&CRYPTO_READ)?"r":"w",file,line);
  776. #endif
  777. /*
  778. if (CRYPTO_LOCK_SSL_CERT == type)
  779. fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
  780. CRYPTO_thread_id(),
  781. mode,file,line);
  782. */
  783. if (mode & CRYPTO_LOCK)
  784. {
  785. /* if (mode & CRYPTO_READ)
  786. rw_rdlock(&(lock_cs[type]));
  787. else
  788. rw_wrlock(&(lock_cs[type])); */
  789. mutex_lock(&(lock_cs[type]));
  790. lock_count[type]++;
  791. }
  792. else
  793. {
  794. /* rw_unlock(&(lock_cs[type])); */
  795. mutex_unlock(&(lock_cs[type]));
  796. }
  797. }
  798. void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
  799. {
  800. SSL_CTX *ssl_ctx[2];
  801. thread_t thread_ctx[MAX_THREAD_NUMBER];
  802. int i;
  803. ssl_ctx[0]=s_ctx;
  804. ssl_ctx[1]=c_ctx;
  805. thr_setconcurrency(thread_number);
  806. for (i=0; i<thread_number; i++)
  807. {
  808. thr_create(NULL, THREAD_STACK_SIZE,
  809. (void *(*)())ndoit,
  810. (void *)ssl_ctx,
  811. 0L,
  812. &(thread_ctx[i]));
  813. }
  814. printf("reaping\n");
  815. for (i=0; i<thread_number; i++)
  816. {
  817. thr_join(thread_ctx[i],NULL,NULL);
  818. }
  819. printf("solaris threads done (%d,%d)\n",
  820. s_ctx->references,c_ctx->references);
  821. }
  822. unsigned long solaris_thread_id(void)
  823. {
  824. unsigned long ret;
  825. ret=(unsigned long)thr_self();
  826. return(ret);
  827. }
  828. #endif /* SOLARIS */
  829. #ifdef IRIX
  830. static usptr_t *arena;
  831. static usema_t **lock_cs;
  832. void thread_setup(void)
  833. {
  834. int i;
  835. char filename[20];
  836. strcpy(filename,"/tmp/mttest.XXXXXX");
  837. mktemp(filename);
  838. usconfig(CONF_STHREADIOOFF);
  839. usconfig(CONF_STHREADMALLOCOFF);
  840. usconfig(CONF_INITUSERS,100);
  841. usconfig(CONF_LOCKTYPE,US_DEBUGPLUS);
  842. arena=usinit(filename);
  843. unlink(filename);
  844. lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(usema_t *));
  845. for (i=0; i<CRYPTO_num_locks(); i++)
  846. {
  847. lock_cs[i]=usnewsema(arena,1);
  848. }
  849. CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id);
  850. CRYPTO_set_locking_callback((void (*)())irix_locking_callback);
  851. }
  852. void thread_cleanup(void)
  853. {
  854. int i;
  855. CRYPTO_set_locking_callback(NULL);
  856. for (i=0; i<CRYPTO_num_locks(); i++)
  857. {
  858. char buf[10];
  859. sprintf(buf,"%2d:",i);
  860. usdumpsema(lock_cs[i],stdout,buf);
  861. usfreesema(lock_cs[i],arena);
  862. }
  863. OPENSSL_free(lock_cs);
  864. }
  865. void irix_locking_callback(int mode, int type, char *file, int line)
  866. {
  867. if (mode & CRYPTO_LOCK)
  868. {
  869. printf("lock %d\n",type);
  870. uspsema(lock_cs[type]);
  871. }
  872. else
  873. {
  874. printf("unlock %d\n",type);
  875. usvsema(lock_cs[type]);
  876. }
  877. }
  878. void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
  879. {
  880. SSL_CTX *ssl_ctx[2];
  881. int thread_ctx[MAX_THREAD_NUMBER];
  882. int i;
  883. ssl_ctx[0]=s_ctx;
  884. ssl_ctx[1]=c_ctx;
  885. for (i=0; i<thread_number; i++)
  886. {
  887. thread_ctx[i]=sproc((void (*)())ndoit,
  888. PR_SADDR|PR_SFDS,(void *)ssl_ctx);
  889. }
  890. printf("reaping\n");
  891. for (i=0; i<thread_number; i++)
  892. {
  893. wait(NULL);
  894. }
  895. printf("irix threads done (%d,%d)\n",
  896. s_ctx->references,c_ctx->references);
  897. }
  898. unsigned long irix_thread_id(void)
  899. {
  900. unsigned long ret;
  901. ret=(unsigned long)getpid();
  902. return(ret);
  903. }
  904. #endif /* IRIX */
  905. #ifdef PTHREADS
  906. static pthread_mutex_t *lock_cs;
  907. static long *lock_count;
  908. void thread_setup(void)
  909. {
  910. int i;
  911. lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
  912. lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
  913. for (i=0; i<CRYPTO_num_locks(); i++)
  914. {
  915. lock_count[i]=0;
  916. pthread_mutex_init(&(lock_cs[i]),NULL);
  917. }
  918. CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
  919. CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
  920. }
  921. void thread_cleanup(void)
  922. {
  923. int i;
  924. CRYPTO_set_locking_callback(NULL);
  925. fprintf(stderr,"cleanup\n");
  926. for (i=0; i<CRYPTO_num_locks(); i++)
  927. {
  928. pthread_mutex_destroy(&(lock_cs[i]));
  929. fprintf(stderr,"%8ld:%s\n",lock_count[i],
  930. CRYPTO_get_lock_name(i));
  931. }
  932. OPENSSL_free(lock_cs);
  933. OPENSSL_free(lock_count);
  934. fprintf(stderr,"done cleanup\n");
  935. }
  936. void pthreads_locking_callback(int mode, int type, char *file,
  937. int line)
  938. {
  939. #ifdef undef
  940. fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
  941. CRYPTO_thread_id(),
  942. (mode&CRYPTO_LOCK)?"l":"u",
  943. (type&CRYPTO_READ)?"r":"w",file,line);
  944. #endif
  945. /*
  946. if (CRYPTO_LOCK_SSL_CERT == type)
  947. fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
  948. CRYPTO_thread_id(),
  949. mode,file,line);
  950. */
  951. if (mode & CRYPTO_LOCK)
  952. {
  953. pthread_mutex_lock(&(lock_cs[type]));
  954. lock_count[type]++;
  955. }
  956. else
  957. {
  958. pthread_mutex_unlock(&(lock_cs[type]));
  959. }
  960. }
  961. void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
  962. {
  963. SSL_CTX *ssl_ctx[2];
  964. pthread_t thread_ctx[MAX_THREAD_NUMBER];
  965. int i;
  966. ssl_ctx[0]=s_ctx;
  967. ssl_ctx[1]=c_ctx;
  968. /*
  969. thr_setconcurrency(thread_number);
  970. */
  971. for (i=0; i<thread_number; i++)
  972. {
  973. pthread_create(&(thread_ctx[i]), NULL,
  974. (void *(*)())ndoit, (void *)ssl_ctx);
  975. }
  976. printf("reaping\n");
  977. for (i=0; i<thread_number; i++)
  978. {
  979. pthread_join(thread_ctx[i],NULL);
  980. }
  981. printf("pthreads threads done (%d,%d)\n",
  982. s_ctx->references,c_ctx->references);
  983. }
  984. unsigned long pthreads_thread_id(void)
  985. {
  986. unsigned long ret;
  987. ret=(unsigned long)pthread_self();
  988. return(ret);
  989. }
  990. #endif /* PTHREADS */
  991. #ifdef OPENSSL_SYS_NETWARE
  992. void thread_setup(void)
  993. {
  994. int i;
  995. lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(MPKMutex));
  996. lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
  997. for (i=0; i<CRYPTO_num_locks(); i++)
  998. {
  999. lock_count[i]=0;
  1000. lock_cs[i]=MPKMutexAlloc("OpenSSL mutex");
  1001. }
  1002. ThreadSem = MPKSemaphoreAlloc("OpenSSL mttest semaphore", 0 );
  1003. CRYPTO_set_id_callback((unsigned long (*)())netware_thread_id);
  1004. CRYPTO_set_locking_callback((void (*)())netware_locking_callback);
  1005. }
  1006. void thread_cleanup(void)
  1007. {
  1008. int i;
  1009. CRYPTO_set_locking_callback(NULL);
  1010. fprintf(stdout,"thread_cleanup\n");
  1011. for (i=0; i<CRYPTO_num_locks(); i++)
  1012. {
  1013. MPKMutexFree(lock_cs[i]);
  1014. fprintf(stdout,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
  1015. }
  1016. OPENSSL_free(lock_cs);
  1017. OPENSSL_free(lock_count);
  1018. MPKSemaphoreFree(ThreadSem);
  1019. fprintf(stdout,"done cleanup\n");
  1020. }
  1021. void netware_locking_callback(int mode, int type, char *file, int line)
  1022. {
  1023. if (mode & CRYPTO_LOCK)
  1024. {
  1025. MPKMutexLock(lock_cs[type]);
  1026. lock_count[type]++;
  1027. }
  1028. else
  1029. MPKMutexUnlock(lock_cs[type]);
  1030. }
  1031. void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
  1032. {
  1033. SSL_CTX *ssl_ctx[2];
  1034. int i;
  1035. ssl_ctx[0]=s_ctx;
  1036. ssl_ctx[1]=c_ctx;
  1037. for (i=0; i<thread_number; i++)
  1038. {
  1039. BeginThread( (void(*)(void*))ndoit, NULL, THREAD_STACK_SIZE,
  1040. (void*)ssl_ctx);
  1041. ThreadSwitchWithDelay();
  1042. }
  1043. printf("reaping\n");
  1044. /* loop until all threads have signaled the semaphore */
  1045. for (i=0; i<thread_number; i++)
  1046. {
  1047. MPKSemaphoreWait(ThreadSem);
  1048. }
  1049. printf("netware threads done (%d,%d)\n",
  1050. s_ctx->references,c_ctx->references);
  1051. }
  1052. unsigned long netware_thread_id(void)
  1053. {
  1054. unsigned long ret;
  1055. ret=(unsigned long)GetThreadID();
  1056. return(ret);
  1057. }
  1058. #endif /* NETWARE */
  1059. #ifdef BEOS_THREADS
  1060. #include <Locker.h>
  1061. static BLocker** lock_cs;
  1062. static long* lock_count;
  1063. void thread_setup(void)
  1064. {
  1065. int i;
  1066. lock_cs=(BLocker**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(BLocker*));
  1067. lock_count=(long*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
  1068. for (i=0; i<CRYPTO_num_locks(); i++)
  1069. {
  1070. lock_count[i]=0;
  1071. lock_cs[i] = new BLocker(CRYPTO_get_lock_name(i));
  1072. }
  1073. CRYPTO_set_id_callback((unsigned long (*)())beos_thread_id);
  1074. CRYPTO_set_locking_callback(beos_locking_callback);
  1075. }
  1076. void thread_cleanup(void)
  1077. {
  1078. int i;
  1079. CRYPTO_set_locking_callback(NULL);
  1080. fprintf(stderr,"cleanup\n");
  1081. for (i=0; i<CRYPTO_num_locks(); i++)
  1082. {
  1083. delete lock_cs[i];
  1084. fprintf(stderr,"%8ld:%s\n",lock_count[i],
  1085. CRYPTO_get_lock_name(i));
  1086. }
  1087. OPENSSL_free(lock_cs);
  1088. OPENSSL_free(lock_count);
  1089. fprintf(stderr,"done cleanup\n");
  1090. }
  1091. void beos_locking_callback(int mode, int type, const char *file, int line)
  1092. {
  1093. #if 0
  1094. fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
  1095. CRYPTO_thread_id(),
  1096. (mode&CRYPTO_LOCK)?"l":"u",
  1097. (type&CRYPTO_READ)?"r":"w",file,line);
  1098. #endif
  1099. if (mode & CRYPTO_LOCK)
  1100. {
  1101. lock_cs[type]->Lock();
  1102. lock_count[type]++;
  1103. }
  1104. else
  1105. {
  1106. lock_cs[type]->Unlock();
  1107. }
  1108. }
  1109. void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
  1110. {
  1111. SSL_CTX *ssl_ctx[2];
  1112. thread_id thread_ctx[MAX_THREAD_NUMBER];
  1113. int i;
  1114. ssl_ctx[0]=s_ctx;
  1115. ssl_ctx[1]=c_ctx;
  1116. for (i=0; i<thread_number; i++)
  1117. {
  1118. thread_ctx[i] = spawn_thread((thread_func)ndoit,
  1119. NULL, B_NORMAL_PRIORITY, (void *)ssl_ctx);
  1120. resume_thread(thread_ctx[i]);
  1121. }
  1122. printf("waiting...\n");
  1123. for (i=0; i<thread_number; i++)
  1124. {
  1125. status_t result;
  1126. wait_for_thread(thread_ctx[i], &result);
  1127. }
  1128. printf("beos threads done (%d,%d)\n",
  1129. s_ctx->references,c_ctx->references);
  1130. }
  1131. unsigned long beos_thread_id(void)
  1132. {
  1133. unsigned long ret;
  1134. ret=(unsigned long)find_thread(NULL);
  1135. return(ret);
  1136. }
  1137. #endif /* BEOS_THREADS */