Back to Index Page generated: Feb 22, 2026, 1:21:04 AM

Oolite 1.92

Content

Warnings

  1. Syntax Error Resources/Config/keyconfig.plist[87:29] extraneous input '0"' expecting {'}', ';'}
  2. Found 1 issues in Resources/Config/keyconfig.plist
  3. Syntax Error Resources/Config/keyconfig2.plist[346:19] token recognition error at: '?'
  4. Syntax Error Resources/Config/keyconfig2.plist[351:19] token recognition error at: '?'
  5. Syntax Error Resources/Config/keyconfig2.plist[346:20] mismatched input ';\r\n shift = true;\r\n });\r\n\r\n key_market_filter_cycle = ({\r\n key = ' expecting {'}', ';'}
  6. Syntax Error Resources/Config/keyconfig2.plist[355:19] token recognition error at: '/"'
  7. Syntax Error Resources/Config/keyconfig2.plist[356:9] mismatched input ',' expecting {'}', ';'}
  8. Syntax Error Resources/Config/keyconfig2.plist[859:19] token recognition error at: '?'
  9. Syntax Error Resources/Config/keyconfig2.plist[864:19] token recognition error at: '?'
  10. Syntax Error Resources/Config/keyconfig2.plist[868:19] token recognition error at: '/"'
  11. Syntax Error Resources/Config/keyconfig2.plist[1374:19] token recognition error at: '?'
  12. Syntax Error Resources/Config/keyconfig2.plist[1379:19] token recognition error at: '?'
  13. Syntax Error Resources/Config/keyconfig2.plist[1383:19] token recognition error at: '/"'
  14. Syntax Error Resources/Config/keyconfig2.plist[1889:19] token recognition error at: '?'
  15. Syntax Error Resources/Config/keyconfig2.plist[1894:19] token recognition error at: '?'
  16. Syntax Error Resources/Config/keyconfig2.plist[1898:19] token recognition error at: '/"'
  17. Syntax Error Resources/Config/keyconfig2.plist[2404:19] token recognition error at: '?'
  18. Syntax Error Resources/Config/keyconfig2.plist[2409:19] token recognition error at: '?'
  19. Syntax Error Resources/Config/keyconfig2.plist[2413:19] token recognition error at: '/"'
  20. Syntax Error Resources/Config/keyconfig2.plist[2932:19] token recognition error at: '?'
  21. Syntax Error Resources/Config/keyconfig2.plist[2937:19] token recognition error at: '?'
  22. Syntax Error Resources/Config/keyconfig2.plist[2941:19] token recognition error at: '/"'
  23. Syntax Error Resources/Config/keyconfig2.plist[3445:19] token recognition error at: '?'
  24. Syntax Error Resources/Config/keyconfig2.plist[3450:19] token recognition error at: '?'
  25. Syntax Error Resources/Config/keyconfig2.plist[3454:19] token recognition error at: '/"'
  26. Syntax Error Resources/Config/keyconfig2.plist[3961:19] token recognition error at: '?'
  27. Syntax Error Resources/Config/keyconfig2.plist[3966:19] token recognition error at: '?'
  28. Syntax Error Resources/Config/keyconfig2.plist[3970:19] token recognition error at: '/"'
  29. Syntax Error Resources/Config/keyconfig2.plist[4475:19] token recognition error at: '?'
  30. Syntax Error Resources/Config/keyconfig2.plist[4480:19] token recognition error at: '?'
  31. Syntax Error Resources/Config/keyconfig2.plist[4484:19] token recognition error at: '/"'
  32. Syntax Error Resources/Config/keyconfig2.plist[4988:19] token recognition error at: '?'
  33. Syntax Error Resources/Config/keyconfig2.plist[4993:19] token recognition error at: '?'
  34. Syntax Error Resources/Config/keyconfig2.plist[4997:19] token recognition error at: '/"'
  35. Syntax Error Resources/Config/keyconfig2.plist[5504:19] token recognition error at: '?'
  36. Syntax Error Resources/Config/keyconfig2.plist[5509:19] token recognition error at: '?'
  37. Syntax Error Resources/Config/keyconfig2.plist[5513:19] token recognition error at: '/"'
  38. Syntax Error Resources/Config/keyconfig2.plist[6019:19] token recognition error at: '?'
  39. Syntax Error Resources/Config/keyconfig2.plist[6024:19] token recognition error at: '?'
  40. Syntax Error Resources/Config/keyconfig2.plist[6028:19] token recognition error at: '/"'
  41. Syntax Error Resources/Config/keyconfig2.plist[6536:19] token recognition error at: '?'
  42. Syntax Error Resources/Config/keyconfig2.plist[6541:19] token recognition error at: '?'
  43. Syntax Error Resources/Config/keyconfig2.plist[6545:19] token recognition error at: '/"'
  44. Syntax Error Resources/Config/keyconfig2.plist[7052:19] token recognition error at: '?'
  45. Syntax Error Resources/Config/keyconfig2.plist[7057:19] token recognition error at: '?'
  46. Syntax Error Resources/Config/keyconfig2.plist[7061:19] token recognition error at: '/"'
  47. Syntax Error Resources/Config/keyconfig2.plist[7567:19] token recognition error at: '?'
  48. Syntax Error Resources/Config/keyconfig2.plist[7572:19] token recognition error at: '?'
  49. Syntax Error Resources/Config/keyconfig2.plist[7576:19] token recognition error at: '/"'
  50. Syntax Error Resources/Config/keyconfig2.plist[8083:19] token recognition error at: '?'
  51. Syntax Error Resources/Config/keyconfig2.plist[8088:19] token recognition error at: '?'
  52. Syntax Error Resources/Config/keyconfig2.plist[8092:19] token recognition error at: '/"'
  53. Found 50 issues in Resources/Config/keyconfig2.plist
  54. Syntax Error Resources/Config/logcontrol.plist[31:1] token recognition error at: '$'
  55. Syntax Error Resources/Config/logcontrol.plist[31:19] token recognition error at: '$'
  56. Syntax Error Resources/Config/logcontrol.plist[32:1] token recognition error at: '$'
  57. Syntax Error Resources/Config/logcontrol.plist[33:1] token recognition error at: '$'
  58. Syntax Error Resources/Config/logcontrol.plist[34:1] token recognition error at: '$'
  59. Syntax Error Resources/Config/logcontrol.plist[35:1] token recognition error at: '$'
  60. Syntax Error Resources/Config/logcontrol.plist[36:1] token recognition error at: '$'
  61. Syntax Error Resources/Config/logcontrol.plist[36:22] token recognition error at: '$'
  62. Syntax Error Resources/Config/logcontrol.plist[37:1] token recognition error at: '$'
  63. Syntax Error Resources/Config/logcontrol.plist[38:1] token recognition error at: '$'
  64. Syntax Error Resources/Config/logcontrol.plist[38:22] token recognition error at: '$'
  65. Syntax Error Resources/Config/logcontrol.plist[39:1] token recognition error at: '$'
  66. Syntax Error Resources/Config/logcontrol.plist[43:23] token recognition error at: '$'
  67. Syntax Error Resources/Config/logcontrol.plist[54:24] token recognition error at: '$'
  68. Syntax Error Resources/Config/logcontrol.plist[55:25] token recognition error at: '$'
  69. Syntax Error Resources/Config/logcontrol.plist[63:30] token recognition error at: '$'
  70. Syntax Error Resources/Config/logcontrol.plist[66:19] token recognition error at: '$'
  71. Syntax Error Resources/Config/logcontrol.plist[71:37] token recognition error at: '$'
  72. Syntax Error Resources/Config/logcontrol.plist[74:29] token recognition error at: '$'
  73. Syntax Error Resources/Config/logcontrol.plist[75:31] token recognition error at: '$'
  74. Syntax Error Resources/Config/logcontrol.plist[76:57] token recognition error at: '$'
  75. Syntax Error Resources/Config/logcontrol.plist[77:25] token recognition error at: '$'
  76. Syntax Error Resources/Config/logcontrol.plist[81:28] token recognition error at: '$'
  77. Syntax Error Resources/Config/logcontrol.plist[83:31] token recognition error at: '$'
  78. Syntax Error Resources/Config/logcontrol.plist[84:30] token recognition error at: '$'
  79. Syntax Error Resources/Config/logcontrol.plist[90:22] token recognition error at: '$'
  80. Syntax Error Resources/Config/logcontrol.plist[94:34] token recognition error at: '$'
  81. Syntax Error Resources/Config/logcontrol.plist[97:1] token recognition error at: '$'
  82. Syntax Error Resources/Config/logcontrol.plist[98:1] token recognition error at: '$'
  83. Syntax Error Resources/Config/logcontrol.plist[98:25] token recognition error at: '$'
  84. Syntax Error Resources/Config/logcontrol.plist[99:1] token recognition error at: '$'
  85. Syntax Error Resources/Config/logcontrol.plist[100:25] token recognition error at: '$'
  86. Syntax Error Resources/Config/logcontrol.plist[101:27] token recognition error at: '$'
  87. Syntax Error Resources/Config/logcontrol.plist[102:27] token recognition error at: '$'
  88. Syntax Error Resources/Config/logcontrol.plist[108:28] token recognition error at: '$'
  89. Syntax Error Resources/Config/logcontrol.plist[109:31] token recognition error at: '$'
  90. Syntax Error Resources/Config/logcontrol.plist[110:37] token recognition error at: '$'
  91. Syntax Error Resources/Config/logcontrol.plist[111:30] token recognition error at: '$'
  92. Syntax Error Resources/Config/logcontrol.plist[112:37] token recognition error at: '$'
  93. Syntax Error Resources/Config/logcontrol.plist[113:33] token recognition error at: '$'
  94. Syntax Error Resources/Config/logcontrol.plist[114:32] token recognition error at: '$'
  95. Syntax Error Resources/Config/logcontrol.plist[115:29] token recognition error at: '$'
  96. Syntax Error Resources/Config/logcontrol.plist[116:28] token recognition error at: '$'
  97. Syntax Error Resources/Config/logcontrol.plist[117:31] token recognition error at: '$'
  98. Syntax Error Resources/Config/logcontrol.plist[118:31] token recognition error at: '$'
  99. Syntax Error Resources/Config/logcontrol.plist[119:25] token recognition error at: '$'
  100. Syntax Error Resources/Config/logcontrol.plist[122:35] token recognition error at: '$'
  101. Syntax Error Resources/Config/logcontrol.plist[124:32] token recognition error at: '$'
  102. Syntax Error Resources/Config/logcontrol.plist[126:30] token recognition error at: '$'
  103. Syntax Error Resources/Config/logcontrol.plist[128:37] token recognition error at: '$'
  104. Syntax Error Resources/Config/logcontrol.plist[129:33] token recognition error at: '$'
  105. Syntax Error Resources/Config/logcontrol.plist[130:28] token recognition error at: '$'
  106. Syntax Error Resources/Config/logcontrol.plist[137:1] token recognition error at: '$'
  107. Syntax Error Resources/Config/logcontrol.plist[137:25] token recognition error at: '$'
  108. Syntax Error Resources/Config/logcontrol.plist[138:31] token recognition error at: '$'
  109. Syntax Error Resources/Config/logcontrol.plist[139:26] token recognition error at: '$'
  110. Syntax Error Resources/Config/logcontrol.plist[141:34] token recognition error at: '$'
  111. Syntax Error Resources/Config/logcontrol.plist[143:36] token recognition error at: '$'
  112. Syntax Error Resources/Config/logcontrol.plist[147:36] token recognition error at: '$'
  113. Syntax Error Resources/Config/logcontrol.plist[151:31] token recognition error at: '$'
  114. Syntax Error Resources/Config/logcontrol.plist[170:32] token recognition error at: '$'
  115. Syntax Error Resources/Config/logcontrol.plist[189:25] token recognition error at: '$'
  116. Syntax Error Resources/Config/logcontrol.plist[192:25] token recognition error at: '$'
  117. Syntax Error Resources/Config/logcontrol.plist[202:22] token recognition error at: '$'
  118. Syntax Error Resources/Config/logcontrol.plist[203:23] token recognition error at: '$'
  119. Syntax Error Resources/Config/logcontrol.plist[204:24] token recognition error at: '$'
  120. Syntax Error Resources/Config/logcontrol.plist[205:30] token recognition error at: '$'
  121. Syntax Error Resources/Config/logcontrol.plist[206:28] token recognition error at: '$'
  122. Syntax Error Resources/Config/logcontrol.plist[208:26] token recognition error at: '$'
  123. Syntax Error Resources/Config/logcontrol.plist[213:30] token recognition error at: '$'
  124. Syntax Error Resources/Config/logcontrol.plist[215:1] token recognition error at: '$'
  125. Syntax Error Resources/Config/logcontrol.plist[215:22] token recognition error at: '$'
  126. Syntax Error Resources/Config/logcontrol.plist[216:27] token recognition error at: '$'
  127. Syntax Error Resources/Config/logcontrol.plist[217:25] token recognition error at: '$'
  128. Syntax Error Resources/Config/logcontrol.plist[221:31] token recognition error at: '$'
  129. Syntax Error Resources/Config/logcontrol.plist[222:34] token recognition error at: '$'
  130. Syntax Error Resources/Config/logcontrol.plist[223:31] token recognition error at: '$'
  131. Syntax Error Resources/Config/logcontrol.plist[226:37] token recognition error at: '$'
  132. Syntax Error Resources/Config/logcontrol.plist[237:22] token recognition error at: '$'
  133. Syntax Error Resources/Config/logcontrol.plist[239:25] token recognition error at: '$'
  134. Syntax Error Resources/Config/logcontrol.plist[240:22] token recognition error at: '$'
  135. Syntax Error Resources/Config/logcontrol.plist[250:30] token recognition error at: '$'
  136. Syntax Error Resources/Config/logcontrol.plist[251:32] token recognition error at: '$'
  137. Syntax Error Resources/Config/logcontrol.plist[255:22] token recognition error at: '$'
  138. Syntax Error Resources/Config/logcontrol.plist[273:28] token recognition error at: '$'
  139. Syntax Error Resources/Config/logcontrol.plist[289:22] token recognition error at: '$'
  140. Syntax Error Resources/Config/logcontrol.plist[297:36] token recognition error at: '$'
  141. Syntax Error Resources/Config/logcontrol.plist[298:35] token recognition error at: '$'
  142. Syntax Error Resources/Config/logcontrol.plist[300:34] token recognition error at: '$'
  143. Syntax Error Resources/Config/logcontrol.plist[306:28] token recognition error at: '$'
  144. Syntax Error Resources/Config/logcontrol.plist[307:29] token recognition error at: '$'
  145. Syntax Error Resources/Config/logcontrol.plist[308:28] token recognition error at: '$'
  146. Syntax Error Resources/Config/logcontrol.plist[310:28] token recognition error at: '$'
  147. Syntax Error Resources/Config/logcontrol.plist[311:32] token recognition error at: '$'
  148. Syntax Error Resources/Config/logcontrol.plist[314:1] token recognition error at: '$'
  149. Syntax Error Resources/Config/logcontrol.plist[315:30] token recognition error at: '$'
  150. Syntax Error Resources/Config/logcontrol.plist[316:26] token recognition error at: '$'
  151. Syntax Error Resources/Config/logcontrol.plist[318:34] token recognition error at: '$'
  152. Syntax Error Resources/Config/logcontrol.plist[320:42] token recognition error at: '$'
  153. Syntax Error Resources/Config/logcontrol.plist[322:31] token recognition error at: '$'
  154. Syntax Error Resources/Config/logcontrol.plist[326:25] token recognition error at: '$'
  155. Syntax Error Resources/Config/logcontrol.plist[327:29] token recognition error at: '$'
  156. Syntax Error Resources/Config/logcontrol.plist[330:28] token recognition error at: '$'
  157. Syntax Error Resources/Config/logcontrol.plist[333:1] token recognition error at: '$'
  158. Syntax Error Resources/Config/logcontrol.plist[333:22] token recognition error at: '$'
  159. Syntax Error Resources/Config/logcontrol.plist[334:1] token recognition error at: '$'
  160. Syntax Error Resources/Config/logcontrol.plist[334:22] token recognition error at: '$'
  161. Syntax Error Resources/Config/logcontrol.plist[335:28] token recognition error at: '$'
  162. Syntax Error Resources/Config/logcontrol.plist[336:24] token recognition error at: '$'
  163. Syntax Error Resources/Config/logcontrol.plist[341:37] token recognition error at: '$'
  164. Syntax Error Resources/Config/logcontrol.plist[344:30] token recognition error at: '$'
  165. Syntax Error Resources/Config/logcontrol.plist[345:37] token recognition error at: '$'
  166. Syntax Error Resources/Config/logcontrol.plist[346:28] token recognition error at: '$'
  167. Syntax Error Resources/Config/logcontrol.plist[347:35] token recognition error at: '$'
  168. Syntax Error Resources/Config/logcontrol.plist[355:33] token recognition error at: '$'
  169. Syntax Error Resources/Config/logcontrol.plist[363:28] token recognition error at: '$'
  170. Syntax Error Resources/Config/logcontrol.plist[364:29] token recognition error at: '$'
  171. Syntax Error Resources/Config/logcontrol.plist[381:1] token recognition error at: '$'
  172. Syntax Error Resources/Config/logcontrol.plist[381:22] token recognition error at: '$'
  173. Syntax Error Resources/Config/logcontrol.plist[382:1] token recognition error at: '$'
  174. Syntax Error Resources/Config/logcontrol.plist[383:1] token recognition error at: '$'
  175. Syntax Error Resources/Config/logcontrol.plist[383:27] token recognition error at: '$'
  176. Syntax Error Resources/Config/logcontrol.plist[384:22] token recognition error at: '$'
  177. Syntax Error Resources/Config/logcontrol.plist[385:27] token recognition error at: '$'
  178. Syntax Error Resources/Config/logcontrol.plist[386:34] token recognition error at: '$'
  179. Syntax Error Resources/Config/logcontrol.plist[387:27] token recognition error at: '$'
  180. Syntax Error Resources/Config/logcontrol.plist[388:33] token recognition error at: '$'
  181. Syntax Error Resources/Config/logcontrol.plist[391:35] token recognition error at: '$'
  182. Syntax Error Resources/Config/logcontrol.plist[392:34] token recognition error at: '$'
  183. Syntax Error Resources/Config/logcontrol.plist[395:34] token recognition error at: '$'
  184. Syntax Error Resources/Config/logcontrol.plist[396:32] token recognition error at: '$'
  185. Syntax Error Resources/Config/logcontrol.plist[397:37] token recognition error at: '$'
  186. Syntax Error Resources/Config/logcontrol.plist[398:39] token recognition error at: '$'
  187. Syntax Error Resources/Config/logcontrol.plist[399:39] token recognition error at: '$'
  188. Syntax Error Resources/Config/logcontrol.plist[400:40] token recognition error at: '$'
  189. Syntax Error Resources/Config/logcontrol.plist[401:27] token recognition error at: '$'
  190. Syntax Error Resources/Config/logcontrol.plist[402:26] token recognition error at: '$'
  191. Syntax Error Resources/Config/logcontrol.plist[406:34] token recognition error at: '$'
  192. Syntax Error Resources/Config/logcontrol.plist[407:30] token recognition error at: '$'
  193. Syntax Error Resources/Config/logcontrol.plist[408:28] token recognition error at: '$'
  194. Syntax Error Resources/Config/logcontrol.plist[409:32] token recognition error at: '$'
  195. Syntax Error Resources/Config/logcontrol.plist[410:31] token recognition error at: '$'
  196. Syntax Error Resources/Config/logcontrol.plist[411:36] token recognition error at: '$'
  197. Syntax Error Resources/Config/logcontrol.plist[414:26] token recognition error at: '$'
  198. Syntax Error Resources/Config/logcontrol.plist[417:1] token recognition error at: '$'
  199. Syntax Error Resources/Config/logcontrol.plist[417:22] token recognition error at: '$'
  200. Syntax Error Resources/Config/logcontrol.plist[418:22] token recognition error at: '$'
  201. Syntax Error Resources/Config/logcontrol.plist[419:25] token recognition error at: '$'
  202. Syntax Error Resources/Config/logcontrol.plist[428:27] token recognition error at: '$'
  203. Syntax Error Resources/Config/logcontrol.plist[434:24] token recognition error at: '$'
  204. Syntax Error Resources/Config/logcontrol.plist[454:1] token recognition error at: '$'
  205. Syntax Error Resources/Config/logcontrol.plist[455:25] token recognition error at: '$'
  206. Syntax Error Resources/Config/logcontrol.plist[456:31] token recognition error at: '$'
  207. Syntax Error Resources/Config/logcontrol.plist[457:24] token recognition error at: '$'
  208. Syntax Error Resources/Config/logcontrol.plist[459:31] token recognition error at: '$'
  209. Syntax Error Resources/Config/logcontrol.plist[460:36] token recognition error at: '$'
  210. Syntax Error Resources/Config/logcontrol.plist[462:30] token recognition error at: '$'
  211. Syntax Error Resources/Config/logcontrol.plist[464:37] token recognition error at: '$'
  212. Syntax Error Resources/Config/logcontrol.plist[465:28] token recognition error at: '$'
  213. Syntax Error Resources/Config/logcontrol.plist[466:28] token recognition error at: '$'
  214. Syntax Error Resources/Config/logcontrol.plist[468:31] token recognition error at: '$'
  215. Syntax Error Resources/Config/logcontrol.plist[470:24] token recognition error at: '$'
  216. Syntax Error Resources/Config/logcontrol.plist[473:37] token recognition error at: '$'
  217. Syntax Error Resources/Config/logcontrol.plist[478:32] token recognition error at: '$'
  218. Found 164 issues in Resources/Config/logcontrol.plist
  219. Syntax Error Schemata/hudSchema.plist[18:15] token recognition error at: '$'
  220. Syntax Error Schemata/hudSchema.plist[19:28] token recognition error at: '$'
  221. Syntax Error Schemata/hudSchema.plist[20:18] token recognition error at: '$'
  222. Syntax Error Schemata/hudSchema.plist[25:19] token recognition error at: '$'
  223. Syntax Error Schemata/hudSchema.plist[26:15] token recognition error at: '$'
  224. Syntax Error Schemata/hudSchema.plist[33:21] token recognition error at: '$'
  225. Syntax Error Schemata/hudSchema.plist[34:22] token recognition error at: '$'
  226. Syntax Error Schemata/hudSchema.plist[53:15] token recognition error at: '$'
  227. Syntax Error Schemata/hudSchema.plist[61:1] token recognition error at: '$'
  228. Syntax Error Schemata/hudSchema.plist[63:2] token recognition error at: '$'
  229. Syntax Error Schemata/hudSchema.plist[68:2] token recognition error at: '$'
  230. Syntax Error Schemata/hudSchema.plist[78:2] token recognition error at: '$'
  231. Syntax Error Schemata/hudSchema.plist[83:2] token recognition error at: '$'
  232. Syntax Error Schemata/hudSchema.plist[90:2] token recognition error at: '$'
  233. Syntax Error Schemata/hudSchema.plist[93:15] token recognition error at: '$'
  234. Syntax Error Schemata/hudSchema.plist[97:2] token recognition error at: '$'
  235. Syntax Error Schemata/hudSchema.plist[112:2] token recognition error at: '$'
  236. Syntax Error Schemata/hudSchema.plist[118:2] token recognition error at: '$'
  237. Syntax Error Schemata/hudSchema.plist[128:14] token recognition error at: '$'
  238. Syntax Error Schemata/hudSchema.plist[134:2] token recognition error at: '$'
  239. Syntax Error Schemata/hudSchema.plist[146:14] token recognition error at: '$'
  240. Found 21 issues in Schemata/hudSchema.plist
  241. Syntax Error Schemata/plistschema.plist[10:8] token recognition error at: '$'
  242. Syntax Error Schemata/plistschema.plist[12:1] token recognition error at: '$'
  243. Syntax Error Schemata/plistschema.plist[14:2] token recognition error at: '$'
  244. Syntax Error Schemata/plistschema.plist[19:4] token recognition error at: '$'
  245. Syntax Error Schemata/plistschema.plist[20:4] token recognition error at: '$'
  246. Syntax Error Schemata/plistschema.plist[21:4] token recognition error at: '$'
  247. Syntax Error Schemata/plistschema.plist[22:4] token recognition error at: '$'
  248. Syntax Error Schemata/plistschema.plist[23:4] token recognition error at: '$'
  249. Syntax Error Schemata/plistschema.plist[24:4] token recognition error at: '$'
  250. Syntax Error Schemata/plistschema.plist[25:4] token recognition error at: '$'
  251. Syntax Error Schemata/plistschema.plist[26:4] token recognition error at: '$'
  252. Syntax Error Schemata/plistschema.plist[27:4] token recognition error at: '$'
  253. Syntax Error Schemata/plistschema.plist[28:4] token recognition error at: '$'
  254. Syntax Error Schemata/plistschema.plist[29:4] token recognition error at: '$'
  255. Syntax Error Schemata/plistschema.plist[33:2] token recognition error at: '$'
  256. Syntax Error Schemata/plistschema.plist[38:4] token recognition error at: '$'
  257. Syntax Error Schemata/plistschema.plist[39:4] token recognition error at: '$'
  258. Syntax Error Schemata/plistschema.plist[40:4] token recognition error at: '$'
  259. Syntax Error Schemata/plistschema.plist[41:4] token recognition error at: '$'
  260. Syntax Error Schemata/plistschema.plist[42:4] token recognition error at: '$'
  261. Syntax Error Schemata/plistschema.plist[43:4] token recognition error at: '$'
  262. Syntax Error Schemata/plistschema.plist[44:4] token recognition error at: '$'
  263. Syntax Error Schemata/plistschema.plist[45:4] token recognition error at: '$'
  264. Syntax Error Schemata/plistschema.plist[46:4] token recognition error at: '$'
  265. Syntax Error Schemata/plistschema.plist[47:4] token recognition error at: '$'
  266. Syntax Error Schemata/plistschema.plist[48:4] token recognition error at: '$'
  267. Syntax Error Schemata/plistschema.plist[52:2] token recognition error at: '$'
  268. Syntax Error Schemata/plistschema.plist[73:2] token recognition error at: '$'
  269. Syntax Error Schemata/plistschema.plist[78:4] token recognition error at: '$'
  270. Syntax Error Schemata/plistschema.plist[83:15] token recognition error at: '$'
  271. Syntax Error Schemata/plistschema.plist[90:2] token recognition error at: '$'
  272. Syntax Error Schemata/plistschema.plist[98:2] token recognition error at: '$'
  273. Syntax Error Schemata/plistschema.plist[109:15] token recognition error at: '$'
  274. Syntax Error Schemata/plistschema.plist[110:23] token recognition error at: '$'
  275. Syntax Error Schemata/plistschema.plist[111:23] token recognition error at: '$'
  276. Syntax Error Schemata/plistschema.plist[112:26] token recognition error at: '$'
  277. Syntax Error Schemata/plistschema.plist[119:2] token recognition error at: '$'
  278. Syntax Error Schemata/plistschema.plist[132:18] token recognition error at: '$'
  279. Syntax Error Schemata/plistschema.plist[137:2] token recognition error at: '$'
  280. Syntax Error Schemata/plistschema.plist[150:18] token recognition error at: '$'
  281. Syntax Error Schemata/plistschema.plist[154:17] token recognition error at: '$'
  282. Syntax Error Schemata/plistschema.plist[166:2] token recognition error at: '$'
  283. Syntax Error Schemata/plistschema.plist[187:2] token recognition error at: '$'
  284. Syntax Error Schemata/plistschema.plist[208:2] token recognition error at: '$'
  285. Syntax Error Schemata/plistschema.plist[228:2] token recognition error at: '$'
  286. Syntax Error Schemata/plistschema.plist[245:15] token recognition error at: '$'
  287. Syntax Error Schemata/plistschema.plist[250:2] token recognition error at: '$'
  288. Syntax Error Schemata/plistschema.plist[264:17] token recognition error at: '$'
  289. Syntax Error Schemata/plistschema.plist[271:2] token recognition error at: '$'
  290. Syntax Error Schemata/plistschema.plist[282:17] token recognition error at: '$'
  291. Syntax Error Schemata/plistschema.plist[290:2] token recognition error at: '$'
  292. Syntax Error Schemata/plistschema.plist[300:21] token recognition error at: '$'
  293. Syntax Error Schemata/plistschema.plist[304:18] token recognition error at: '$'
  294. Syntax Error Schemata/plistschema.plist[309:2] token recognition error at: '$'
  295. Syntax Error Schemata/plistschema.plist[319:21] token recognition error at: '$'
  296. Syntax Error Schemata/plistschema.plist[323:18] token recognition error at: '$'
  297. Syntax Error Schemata/plistschema.plist[327:17] token recognition error at: '$'
  298. Syntax Error Schemata/plistschema.plist[339:2] token recognition error at: '$'
  299. Syntax Error Schemata/plistschema.plist[349:21] token recognition error at: '$'
  300. Syntax Error Schemata/plistschema.plist[354:17] token recognition error at: '$'
  301. Syntax Error Schemata/plistschema.plist[360:2] token recognition error at: '$'
  302. Syntax Error Schemata/plistschema.plist[370:21] token recognition error at: '$'
  303. Syntax Error Schemata/plistschema.plist[372:17] token recognition error at: '$'
  304. Syntax Error Schemata/plistschema.plist[378:2] token recognition error at: '$'
  305. Syntax Error Schemata/plistschema.plist[383:4] token recognition error at: '$'
  306. Syntax Error Schemata/plistschema.plist[388:15] token recognition error at: '$'
  307. Syntax Error Schemata/plistschema.plist[389:23] token recognition error at: '$'
  308. Syntax Error Schemata/plistschema.plist[398:2] token recognition error at: '$'
  309. Syntax Error Schemata/plistschema.plist[410:2] token recognition error at: '$'
  310. Syntax Error Schemata/plistschema.plist[427:2] token recognition error at: '$'
  311. Syntax Error Schemata/plistschema.plist[431:15] token recognition error at: '$'
  312. Found 71 issues in Schemata/plistschema.plist
  313. Syntax Error Schemata/shipdataEntrySchema.plist[165:1] token recognition error at: '$'
  314. Syntax Error Schemata/shipdataEntrySchema.plist[168:2] token recognition error at: '$'
  315. Syntax Error Schemata/shipdataEntrySchema.plist[237:2] token recognition error at: '$'
  316. Syntax Error Schemata/shipdataEntrySchema.plist[277:2] token recognition error at: '$'
  317. Syntax Error Schemata/shipdataEntrySchema.plist[295:2] token recognition error at: '$'
  318. Syntax Error Schemata/shipdataEntrySchema.plist[311:2] token recognition error at: '$'
  319. Syntax Error Schemata/shipdataEntrySchema.plist[335:2] token recognition error at: '$'
  320. Syntax Error Schemata/shipdataEntrySchema.plist[346:2] token recognition error at: '$'
  321. Syntax Error Schemata/shipdataEntrySchema.plist[361:2] token recognition error at: '$'
  322. Syntax Error Schemata/shipdataEntrySchema.plist[372:2] token recognition error at: '$'
  323. Syntax Error Schemata/shipdataEntrySchema.plist[381:2] token recognition error at: '$'
  324. Syntax Error Schemata/shipdataEntrySchema.plist[391:2] token recognition error at: '$'
  325. Syntax Error Schemata/shipdataEntrySchema.plist[401:2] token recognition error at: '$'
  326. Syntax Error Schemata/shipdataEntrySchema.plist[411:2] token recognition error at: '$'
  327. Syntax Error Schemata/shipdataEntrySchema.plist[428:2] token recognition error at: '$'
  328. Syntax Error Schemata/shipdataEntrySchema.plist[434:2] token recognition error at: '$'
  329. Syntax Error Schemata/shipdataEntrySchema.plist[486:2] token recognition error at: '$'
  330. Syntax Error Schemata/shipdataEntrySchema.plist[492:2] token recognition error at: '$'
  331. Syntax Error Schemata/shipdataEntrySchema.plist[498:2] token recognition error at: '$'
  332. Syntax Error Schemata/shipdataEntrySchema.plist[504:2] token recognition error at: '$'
  333. Syntax Error Schemata/shipdataEntrySchema.plist[510:2] token recognition error at: '$'
  334. Syntax Error Schemata/shipdataEntrySchema.plist[516:2] token recognition error at: '$'
  335. Syntax Error Schemata/shipdataEntrySchema.plist[522:2] token recognition error at: '$'
  336. Syntax Error Schemata/shipdataEntrySchema.plist[528:2] token recognition error at: '$'
  337. Syntax Error Schemata/shipdataEntrySchema.plist[534:2] token recognition error at: '$'
  338. Syntax Error Schemata/shipdataEntrySchema.plist[540:2] token recognition error at: '$'
  339. Syntax Error Schemata/shipdataEntrySchema.plist[546:2] token recognition error at: '$'
  340. Syntax Error Schemata/shipdataEntrySchema.plist[552:2] token recognition error at: '$'
  341. Found 28 issues in Schemata/shipdataEntrySchema.plist
  342. Syntax Error Schemata/shipyardSchema.plist[13:26] token recognition error at: '$'
  343. Syntax Error Schemata/shipyardSchema.plist[20:29] token recognition error at: '$'
  344. Syntax Error Schemata/shipyardSchema.plist[21:16] token recognition error at: '$'
  345. Syntax Error Schemata/shipyardSchema.plist[36:18] token recognition error at: '$'
  346. Syntax Error Schemata/shipyardSchema.plist[40:1] token recognition error at: '$'
  347. Syntax Error Schemata/shipyardSchema.plist[42:2] token recognition error at: '$'
  348. Syntax Error Schemata/shipyardSchema.plist[47:2] token recognition error at: '$'
  349. Syntax Error Schemata/shipyardSchema.plist[50:15] token recognition error at: '$'
  350. Syntax Error Schemata/shipyardSchema.plist[52:2] token recognition error at: '$'
  351. Syntax Error Schemata/shipyardSchema.plist[66:2] token recognition error at: '$'
  352. Found 10 issues in Schemata/shipyardSchema.plist
  353. Syntax Error tests/scaling/Resources/logcontrol.plist[1:0] mismatched input 'textureLoader' expecting {'(', '{'}
  354. Found 1 issues in tests/scaling/Resources/logcontrol.plist
  355. Syntax Error tools/BBC keys/BBCKeyconfig2.oxp/Config/keyconfig2.plist[367:19] token recognition error at: '?'
  356. Syntax Error tools/BBC keys/BBCKeyconfig2.oxp/Config/keyconfig2.plist[372:19] token recognition error at: '?'
  357. Syntax Error tools/BBC keys/BBCKeyconfig2.oxp/Config/keyconfig2.plist[367:20] mismatched input ';\r\n shift = true;\r\n });\r\n\r\n key_market_filter_cycle = ({\r\n key = ' expecting {'}', ';'}
  358. Syntax Error tools/BBC keys/BBCKeyconfig2.oxp/Config/keyconfig2.plist[376:19] token recognition error at: '/"'
  359. Syntax Error tools/BBC keys/BBCKeyconfig2.oxp/Config/keyconfig2.plist[377:9] mismatched input ',' expecting {'}', ';'}
  360. Found 5 issues in tools/BBC keys/BBCKeyconfig2.oxp/Config/keyconfig2.plist
  361. Syntax Error tools/BBC keys/keyconfig.plist[61:26] extraneous input '0"' expecting {'}', ';'}
  362. Found 1 issues in tools/BBC keys/keyconfig.plist
  363. Character reference "&#x8" is an invalid XML character. (Fatal)
  364. Could not access: https://github.com/OoliteProject/oolite/releases/download/1.92/oolite-source-1.92.zip, org.xml.sax.SAXParseException: Character reference "&#x8" is an invalid XML character.

Manifest

Identifieroolite.core
TitleOolite 1.92
Categoryvanilla
Authorgithub-actions[bot]
Version1.92
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URLn/a
Download URLhttps://github.com/OoliteProject/oolite/releases/download/1.92/oolite-source-1.92.zip
Licensen/a
File Sizen/a
Upload date2026-02-02T16:26:02Z or { uploadDateAsInstant!"n/a" }

Documentation

Doc/OoliteReadMe.odt

PKEGA\^�2''mimetypeapplication/vnd.oasis.opendocument.textPKEGA\Configurations2/menubar/PKEGA\Configurations2/progressbar/PKEGA\Configurations2/popupmenu/PKEGA\Configurations2/images/Bitmaps/PKEGA\Configurations2/floater/PKEGA\'Configurations2/accelerator/current.xmlPKPKEGA\Configurations2/toolpanel/PKEGA\Configurations2/statusbar/PKEGA\Configurations2/toolbar/PKEGA\manifest.rdf͓�n�0��<�e��@/r(ʹj��5�X/�޾��VQ�����F3ߎ���aȋ���T4c)%�Hh��+:�.���:�ض+��j���*�wn*9_��-7lϳ�(x��<O�"��8qHƴ�	�Bi��|9��	fWQt렐y� =��:���
a�R��� ��@�	Lʄt��NK�3��Q9�����`�Ӄ�<`�+���ވ��^཰�\��|�hz�czu����#�`�2�O�;y���.��⯴vDl@Σg����UG�PK��h��PKEGA\
styles.xml�]K��8r��W(41>�z��ޘi��tDwu�T��q"!����T�ӆ��>��}����5>�u��A�"H��j5T����2��/�@~U���a�u�q�Ŀ�{�n�6q\}����Oּ��W��Y�\_;�N�؏�(�{8�@e?��›n��Ent�-��c�����e�k�UZB�Mw��u�O+p�	���`0���B{E���y֊X6�(v�^����?e��v��n̺.�>�
U���$���c���igQ����Ǩ����<$fԦ���\;�q��TW�q
W�$�3{�h״'��$w�c�y��S0���������66S.�-��Ĕ��~�]���Q�J@�r�ծ�]��8���Zuyvf�(ǪU��>�Y�s2g'��f0*��~�/�L)�1��p�E�I|�D����Х"�jׅ���v���T'�x�U�*�y�h��(� �v:��w�ָ	|źw��,R��+-���cB�md�>�
	�����(�T�~�B��wo�@n���-�s;t��k�k�%�
S
��a�{���
�C�m(���i�����"�;���-�^��;�|���Lgs��>t�D*��u�}^.W�k�}@
�s�s�����
��#�KN�Aם_}�z�yw��?��D�|��K���b�=et��E�QI��la�����}������a��*�"�40I:�#����{�6R�*ˎ�E�n�'�s�o]�Y$�#>�4�^sS?�ww�w�oo���i�����?���������������O�VƈL�%��흻�K|E���!�b��~�$��K��ͨܽ�I�
=�E6�+j�˨y/-Ѹ�QXi�����TwPn��l��l�'
�#�@��e�/�>�a)�Ѿ�K:Kut8�k�[
�֯:_��<!Sp�
%^�����a�Cl\�+t��VG?�.��N-�C�	C�HW�O�Wh����0
=/��F����vV�zMY$�ٱ�'��V�6�!;F�[7�Ao8�]_)ߗ��ޱY9��ِRZ��	=�r��N����V��i�q�%]U���=��΍7O�Wȋ$'P���vg"�o�$&��<����"/�dn�Ʊ1���'�BB�?:8o�^h�˂{����!�9�l� �!"AD��zؙ:wi6I��>��z�6q�@4�I����oEӲ�dK'G�J���Hs�X���L��A<1+�`M��0W�!A�C�(5kA�|��9W�E�M�Vړ�}�Iڥ��-wLi?(7}�a���2�n��N3ћ�n�r!|4�)�[tk������!���u��7\A��q���f	�o>�N�[�ç�zW�V����z��ܧ�\ٱ��b���-r}v�.7*)I�9T��Z�6
��'�䨱�#�S�FŅ��EPV�=	K',WN�Ia�ò+s�r	c��I��7pd�L�թ[!�t%q�Ɓ�5�7�.�q�X�r�ف�wP�t+Õp*�k:_�����w��h��G��
!|�[���Ѩ�c��D�]�4��0k�/I���E�c|�¥	w߹�"����c���?s����U�r�PZ���	���beV�A��42�GN$�_5�L�z2
�V�)w߿�=�Hd�#G:cU�7(�[�AԧD֣B��q����n�	�[v���i�);��%�c��`����������fH��<�%x�ۡ}t,$J�-e�C�S����k�Z�隗	����$ħhRA"�r�y$�d|��bM�A��:���G8��[}��Y�f�|�ZN](�
�^�
�P�NQ�	����z��c&�(�z����/��6{�'��~%!j���8i�ax�]F�EE	�<�U�A��Tq��e��M׍!尛���R�������(M(��Sj�{o|?<�繬�Z�{"���{
U��{M���N�Z�P�A�5T-
pp\W���}��[EI�ް��n��u���v�8�/����D\�g��ZeS8��c��!���pq�hv�jOp@|rW-=J:,C$���a���M0�8s������p6+U):�pjl5���0ޠr*���6�?�)�f����a�~��m�::u��;,��m~��͘�-���8�rH���1W��>O��+9_��DN�:�7���Wo9��z��]�}ZNu�r���/�:�IJ�>�c?��G��f�Y�0�����/#��	<�7����6m(5�:��q��Ԛa��~�W:ѵ��'��ڙ[Neض�74��1띿��Ohud�B�����x��|;��U�2�/)�N|�3�]OZxӍ��:*;סoz�;7j����RGs��I!fɮlⷕ&N+t2S��:�����K2���q��P^�r�΁Ω)d}��$Z�"�,>��P��=�|v}?��NJT�Hڸ�^�Q^+k�Q��+�����
��w��k�VP�U1���{i՞�8;��+ǚid�I5$"C�q�
��`!�7;B�Ss2yy��~H�p����w��rM�!�d+"e"�0���������O:��3Ғ���X��%AH���$�͟?��E�B�$�j�ٟ�!}m;������1��0tb>�y?�1�����9p�sx��O��W����?C?���iH�'�����{���{����-�ӕ8oAD����~S�����R�Ɋ3Ԙ2o�8Y�>�� ]a�,��ߌ� f�#�
��=PI�f�+�yd�o��jb��J�go��H�qz+�m�.{=�k���m�b��[_9]�VY���G��=7�O*�?Q�r����?~n��������W�������f�i���j�O�a��j�_=7��*�?S�v�O��?}n��W�������U���쿨��Bm��9�?����y����Pe��9,�����Y�Wa�������8�I��
�Q#5�(�dXX[�9}֘��&~��$v�ŭ>�n{�VnG��Zr�� �f�B��\]����&�cݛ������u�1:%�h���_cկ��
X�ͳ���t�d�rn�=�z^0�����Z��@�6�	���*xZ�x�cS��lr���φP-+�2j�Y�e
^>-�����Z^�% �>�W���:6��Ë����3:��S�M���tV|�p/��;��iv Iܘ��@k�Я�5F�h�� ����V��m�-fiO��f�oQ_��|!䩖��5��9B���Ckh���5����z#dh
��1���ZCw�.��������0�5.xQZCw���16���!Ck荏�5�F��cch
�2���]�19�m��9nk���4ڧ͆��!ClbC_l��=B���Cl荐!64���#d�
��b��\���9������yEw|��7B����jh��a5��ǰz#dX
��1���VCw�.�՘~��Pg���(�����X_��o��(4o���P���Cqh���8���Pz#d(��1���Cw�.����P��0��B�Pcc(�2����Co�š16���!Cq���P�s��2?˗n\�Ә�St���z#dh
��1���ZCo|��7B���Ckh���5tG�rh�Źh��Y���%���5����z#dh
��1���ZCo|��7B���Ckh���5tG�rh
�yx���,���b����c�
�2Ć��bC{���7>���!Clh��!6�G��#tA�ư%mю��C���_+���ӱ6�3��Dm�6�3��DXm*�l<U�x�M2�l<���I�����jϵI����j/�Im/��C%��Mbz���-�;��Mr�[r	�#�&��]'!�c�d��P�tW����	��i�]T�$h]|��=��h{��D����T
�U��������aB��QS /�'�U��F0\Lv��I[��@�Me�o�x˼�������J�آ�ܓ$"���E��z����Z�R,��]X1,:��h�����>Lص1���~DIL`��m	o�LY��0CY����7�h�`#P��˪�^��li�eS���?c��x[LL���_`
��|Ԅ��0r@o0!{0�%٨�C�3ڦ�"�iˇ2�l?pin�t���,�*��1��ᒝ���7��E�g�
v����t1ZTzh����"��G�Z%a"7�����%��xIbp�z��F3��R�0]o0��f��O�$�m���͊��soQ���T邞U�%�r��\V��>WS�����Ǖ-�VBvYl)+1dj��F��'�W�iń"���x�hw�r=غ#⹎TR��Il�n��;���|E�]�ڢ����Y u�uB/>q����j��b��l��l
��%�f��x1W(��c�ҡ~��O5��%�b�y���!l��Fy�.�3`��կ^�b��:0��/A(��bP؂1f.e.�uxP��s��)�&?���,�ne_��+{%Y�8�������
���lT&�Å	�&L�0i�d�09�:L.f��:PV���(9�O�_+J��&J�(i���QRAL8A�����������
eCU��4I�@��k��%�SI�Q*O斾RPꤟ(�����9�ڍ#�i�6s��L�-�2�g^�R�u�N9ѓ���yp����)w�_¡ӫ�A�;\)��l�
V�#V.�Q�a��%�����7��O?�r���m������~~�1%Q�ӑ�hٗ�@g���S��#�a�Sk7];	�ÿ��K�i�Q�Yɍ��P�\�����}��9��On����ѵYģ[�%�td��Q��?J����Q�b�򃇁�1�~M�{X�t�C��S�ΰv��S��՜���(��.�PK�0QEc$PKEGA\meta.xml�U�r�6��Shh/�?v��ى��7��8]{��*#�1V�%Fq�H}�>Y��N=���9�w~�s���
�������;���^PVN�o������]M�zM	�'���w�0�T&��5��R�%�)�;��")��
����D���Q�N]�%t���
</r���ZQ�=�����
�O��5�Z�#�nDePq�������ض���B�=m�EQ]*I��:'V�~����B}�'��V6���&&<eTQ\�DV\d9[F�ۉ{�ݑ̓k댐����v�|?ũ���sܤ iOƶ؞��=CH�8{�7qX��T��%�8%N�D�=��C�;`�M���A�#�9��E#L��c�q�
�D����%0F��4�0J��N�N�����������8B'��Z�?�(����ab�$q�^�~>"~���/�8���ѷ|FW�D��Գ�U���P����Tw��hUQ��?�_�ItsP�!�
D8S��&���v������747�*���%�t��-�G��Э��[��q� $��F�?�����:�U_�r��S��07�v���RD%��Pz����{�`������j�0P���«Soj��7Ě͖)�P҂bfK���S�L�Tt2��!|W7JwX��$
Z6.hI��é����T���#~��	��6�d0�d����~m(٢�j[�7���)�<uW��40�(��
�A\|� ����-�\��o����3�Α��~6�����"�,v]�C׼t.��_��I�����+�	o��Z����G����l�z��>A^m�כ�y���V4X��b���-�h<�z'�o��F� [U�c��ѵ���6z��֔���Z���X|�_�=�v�uy�x��������bիuJ�&���ݽ�%��PK��܏�PKEGA\settings.xml�\[o��~�p�h��Z��Z�ڋ�D��Z���uۇ9��"g��в�(��&@Ҧi�@�ܚ�y/���`���rf$y7�d;��ȃ�A��9s9�;����Ó�_8&<��Z\��X\ �f�Gݭ�Jٺ���p�GX���d�av*�DD�-��4����Z�9�d8�M�m
{����|���b6����bC�psiI>Яq�qwi%�X[�k��m^�o�Zw[���r2�\Rw�UmF�{ۆ�k�6h�C���=�a����x�rl�%��E���GZ��8��>S���\f����h�p�g�]�^��`�*����#u1������(z�h�$�����1�⹍�
O�ߘpLJ
�*䆤��$�ĠƘO0]�<&���R��VDr�!�ױݚ���w<��\��"��q��ۍxֹ��HpO�����gr��%W�ONv��l$kK��|�CY��k�"[�$+��S�6�,={��d���@鲸5��U���,)������ǐ��Xsfj}u\,l�Ǵ}c±�F%�[��pAC����;�Cp=
�����0��)�q.@�gZ.����2���&��=��������ѿs9��� y�Ȉ��e}���5�q��A���ڀ�%��{S&�)�L4R,���P��O�&�{�^��ե��7���=p`ƴ��?��/�n���o~��W�9�����y������w^t;ow;ϻ�w�����?t;�v�������[��G��w��}�i����g�/{�o�N�흾�;��w�a����ӏz���N�zg���>�}�;�w����O{/?�}��Ƥ�5����~��߾���W睿�w>�v��v~��|��|������k�����{�ӯ{g�ξ�}�y������Q���p;�Mγ9�X],���-��ք��(����pDƳ��t�b�a����b~zoO�Y	,F9��f�8y�2g��Z�DI`~Y�f��[>�BHN�,�tpl�0�5���>M�&�y�
�g����X����~�`j���ƾr;�u0G:�b`��r�j%҄�9ni�7����Q蜜KJ�bA���>����G���fx���ko-%��'����J2pRF����Z�(�'�Tʇ�S;H>��%���Ƈ�p,���~��!B&�7*�s�FI��-�-u�2��h'�j-��l�#�H�Bd�Q��j�sǃ�&�~l�2��xb��@d �D�%R���<��r�<��h�h�C6�����OV�W�,ɒpv+�
��c�*�լ�.�T+�g�x��r�v�s`4��e^~�ż�ʘ��?��~�dJi�v"�Ch
��F�Pڄ#�C*�����9��B�Gh�m�W��sp߰d���^@������ϩz&�K��v�J��+#�Z����}�l�P%c�������I 3	�Y�������YF��K��_>؁�y\k+k�T��W
U/W0ҵ��c��||���ԫ�fo�T�e�������Sy;����y˵�t9p+�����6в+9�X�/1��XF�܋���bg=������S0�>(\�*�n��������UilW�֘��
䴌X�C�ʘ�ghǖv��v�<i�(�@G��S����;Md#�?'���QtBy��qr^�e^�e^�e^�e^�e^�e^�e^�e^�e^��RJ��ϗ��Q��f�j��F�\I��bw��Z��V>L6���^�p�ׂ�j��ښ�ﹴ�k%��<�<�_6��҃�ynq�|�<������E����"�z�s��bA�I$��<���߮D������C��3�G«�ezVt�F���LU�=�>&�F�(�|=�3>�a?=�"3�t$����)Fy�m��]r���+�c���rM,erԪ�
24�HG.n?�Ej~���%�E�3L��9��B����_��I�""Sj	.�C�&kh
f
=K@�'���C�U�a��
�Q-�\������v���1y�
�m�de~,vRs��k�����&n�t;�ƍb�`GKZZ.:dܑ�,�O@���2ږ?6W~:�9�,H
b!7��c�?�	��Nn
x��_f"!x��*�pr\�8�<IG�J��Tg�ﳖ�`��6�`�/0U����3=�L�|�����^��݆�,���r�q���V����G�
T��!z�uF#�y��
���gE�@����&-ԣ"�o���S
Hf�:���Ӆ����¾��"�"�Q���=R���Zbe�
�{;E�p�j1:)�Qt�
7�r����)+�'����&G�3��7�������l��CBn��K6�M"�
ۈ��=D:�]J�(�[]_O�_�?��S��¬��HC�sX4�C��j�E�;��DŽ�E�>�b��/1�P��%��H��6u���h��IǾ�ɐ�'��2$���
������2�[EK6�Bq-��EI�Q˂�ـB�kj���]�ӎ�.��h��@sj[�c"�냪2'x�t����Z�D�\�v�sd��ڵ6td�j��@F�__���t��(3�� ����L���"�E4�e<kBzm�EC�
�3
��^$���z]J��e��GcG&u(Rz��T�&�o��hd�PO�p�/0� �38��U�r�fK~I�y��,������IW L�b��}�+3)����3q<�.��	�L�3|C!g��j�)'.���t�����&��ڏ���)x��l�%+��7CG �DDA0�
���������s�7���M�/*d�+�EW$�s�c�Q�W����yML���� 
�@뚊�6�Oً���]��` u�W˙�$i��byOW��D~���0K}��e�Ne���T�f�����EE�׎�5�~�j��'5��}lt�[PKܖ힆�TPKEGA\���(�C�CThumbnails/thumbnail.png�PNG


IHDRj���pPLTE	 ($ ))6')%74")+":''&'&*8.257,)72-666.C1E!.C)6G)=S7;F<DK8HY<QfGHW\H3G(%E3&G<:R--S>*V11fdw~b''f11z..w66F?DLC8UA,ZG7bM:kT>HHGDKUKS[VLESO_ZSLXVWGYkH]sX]eX^sMaoMav[ckWgxhLIjXEf[WyLLt^Iu[Ve]gid[wbM{hVhgggkvopnkrzvjhrmvyrixvwUl�]s�hv�i~�vz�x}�TU�yy�z�}o��l��{��y��}��|��y������$$�11�::���::�//�<<�CC�LL�YY�p[�ke�mp�wi�{x�ee�~j�~z�NN�[[�NN�^^�yy�ee�uu���\\�II�\\�kk�qq�jj�]]�}��{���y��{�����������������������������������������������������������������������������������������������������������ě����������ǩ�Ҹ�Ķ�Ѷ�������­�׼�ȷ�ٽ�ټ��ž�߆�Ԟ�Ʋ�ū�Ƿ�Ľ�ԭ�Ӿ�ֲ�㫫ⴴ¿�õ��ź�Ӿ���������������������������������������������������������������������������������������������������������������������lBE�@cIDATx��|�y��T�%�bmՎ�O��Z�Z7��6�6�b�tի�IC�,�2��C�u��:{�m���޺��kp@�����069�_�yM�$��A2W�St��
B�	Ehȁ���I��lK��H���3�3�Ń�}�w�?@�>��"��)j*������)j�������(j������)j*������(j������)j*������)j�������(j������)j*������)j�������(j�z^���!Q���4�M�h�R��>O�::�]�3:�vtP��keQ�U7l��/E}�Uݞ���ZΎ%���zɒ%K{����vɒ���U�����%�t��%m�����&MX/_�����~O4��7��y�&��/Y?���c�-����/m�6��6�e﵊wߒ�+i��.)�K;��+V�X����-$�y��V�����y��W��x�p,Y�����@�U_$�쬯�Q�^����3���W�^`=o՝�
��t�W� �W�^�|ջ�g,�Rr��Ҷ�^��b�^�d�Wۨ׬^���m��5��sV�����͆��qցج�,_u�վ���(ۨW/��-y�����h���z�����-��xF�g���k�Yϣ�����B�dު׮]���
�_�z���d%P�o��<_��f�v�-�2���k׭]{�US�o���_m�^�v�㢒͐|��Ue|��u�H/�^NQ�u�w�Y��u�֭^���(�r}��U���X,1i���z
u �S��8�@V�E�n�G9W�1����ZY=�)�r��v���z�]�� K�E��v���O�^��1�?dy[�G�|��X��:�W�9�W/Y����.Yr�!�DB��|�=�8�8��Wλ���O�;�@ȗԮW/c,��߾ζ�bBH�|r�=��3�=
 �D4o�[���9��,kb�˗ܫ_g7v�n2\b��I�9�z��u��m�6h[6j��d��sf�H��i���Qܳ�Aڕ=���z������@�yԶ�}�S��]PY�E}9Zaeo���zj-���+:�Ǥ.R,Z�>��S;�w 5����^q����Ŷ��j�ߞU�Ε�NJ�V=_Y;_,.��/O�.�굋�=�����s^��c�����:�-�'IY�󩝤�<Ϫ�P��Br�Uۥ�2ی����+;{��m���v����/���t�ž��-�P��*e^�O��:W_�m��ʠ�/O�]��5�u��m3ޚ̐�p�WC|��}�������Q��e+.���\�lW�oC�LF�lG��-;/��\������d���S;W$�mR�4McW�ݵ��z��%+��zC�)j푭���=����[����j떭[�:�Zf�*gWW��ݾ�~6n?_����A63oPԗ���s
��U�E�=��ɝg��'��ռv�ު:E}yr.Yq^
�w�F�O=�-�g��de��g������s�݋����z���]�z�����_���}�/�������?������z�c�3��������y�ϗ���)��?�f͊%]�,CQ_�,xc��5c5��[�_�W��g�[����[�̚��y�-�?յ�aUI!�ז��(���f�r��:���/�Y#���k���g
����x�����U������������_���כ[���f���^{�ݶ�Y�>��D�8H�b��p�
ֿ���1����_'���#��y�Z�$��u㫤|���q��׏�������C����=v��5k^6��b�Tm����׫_�GM�ڈ?I���+J����Ծ�q�7���%�TA�b���{����+�������8���4��������
��?�����������?\۪��l�6�����곟�ۮ��X��r�,]�f����4�O۳�o���o���C��N���h��ϣ��j�R=�۶U�Ҁ���p���k����M�[�v�O���������������?���}��������}'A��~�n��/��N�[��v_�G,������X2(�knZat.�9��z�J|���u<�؊[��Q?CX�5���󟘯Y�iE}�j�ٸ@6���
���\a�^sQ����{;��,7�e�\c[��ϴ+{+��d�	����\ߨ�֜}��@�-�'���%g}���X���~��ܺ�~ �SK�Q?��[�����"����̣^�0)��P�e��~ 6�5+H��ԲՄ�Ύ�Ϋ�<IH[@Q��+מg�Ou�$�W��|��^���Ⱥ[�o�7��o�+��v���	�K�NⱿ�TG���|}zy��~#7�<{UƱt��s/R0>��K�,{��~��y}��8�@Q_
�[֞a�-S2��%v��@V�k�7q��9}ߊ����$3e���;���!�ᆙ���e����$�����ݙ�(�[h�6b�z���w}z~�Q�F��n���N��=�0Zi�XW~����D8;�!��HQ_K96z��RDzOI8~}>l�iP����W~m�X�����5V��[+7�e߀����"�袨��ܝ<��eE}͍�6R�f�
E}�Ŭ�Y���V���P[�س�c�6�g(�k������X�K;?BQ_s�6V��|P��Z�=<�V��޵����]���An�A�]>��}��j����ߟ0�F�h�2EMQSQ��US+s�X����>BQ_���F��������}!��IQ_m}�c��~_�䭖1���T�_�Pʶw���j�[�k���_���?��#�;F�:�G::V�Ďۖ�	E}���x�����?T�?��Q?
��0��Lu�S�WI�:�n��_�XJ̻�c(ڶju��#��j{����&/3w�G?i�~)z֪s(�R�����:>�o��)�J��ytު��C����tt}���j����}�T7�MK;>UX(ɟ���D�/�h�HEQS�5EMQSQ�5EMEQS�T5E���+0�\��
��!03!�����lS����b
�f��kN��饨�P��>i��B�I�|V�g�G�)�9�l�Ჵ��k�W=��w<�ϔoOD�0�)�+�ܧ�>���[G���cW�����o�
���	�r�ÓQ�C�>��]w��Y?���{��_��L�:�+�W֗=�����(������>S{�d���C�V���޻\O?�"���KĪbes�@Q�e�f��F�vm��^w8�ߩ=]�z����p����탣���
O텇k��/N@�EQ�E@QS�T5EMEQS�5EMQSQ�5EMEQS�T5EMQS}pQGG�d�!%o0O�4�r�����{�;=��]��.��M��Q���W����1���E}��y��˟���'��d��m�����٧ÿ��~u��ճ��gj�!ϣ���ԇ	j�K�;=O<=�r��_�>EQ_5e�m�L5�M��8!W"	��J{����S�T5EMQSQ�5EMQS�o��hä��)�'n)>������N)��K)^�YG�#ܙ��cO���G{������5Am}T������o��/���읻�z:k#-)j�������(��
��P��:��yiUN����4�K{sm�m�k�X8o,n!�$�&�R����:*����ͳ�k�(������Y��++��}5F��}u�.���A���	������eP^�P�kH`e��OZf.,E�L
��l8�1���T����$HZ�:�C()�dc�
��gɷ���8��1��"F(`^B�s���ٹ9��=GOLC
�`I	UZ;PB0Ue\Ò��#��\{29���S,#oa������ F���kh�B��*�aλ'!!��E��܇��Y��Ψ(	�o@jJ��އh1�^8�ǡYǐ2�n.��r� ���֮n�xD��:�|8���%:� �/%�l��A@�i�����ٟ��"6r�
��O�H�盙$t����e�'��/'��Op?x\��!�}�o����r&�"�<���u��#���s��-.�<��f�	v��-���s%	�yo8I.��s�^N�@�1�3��Xa�-p�"�g��bX�ʶ��qq��G]�"t|����C	g0>�aW���l���u\�F��X����V%��p)�&qAM@^/Akr4���U�[X�X]Sc��"h�隢a�;�@'[�P,&K���c&٠`rl�\
>n��<�t���q]���Y,���/&!+��Br(&1�S'ץ7p����V^.���1;��K�$`�8	�q��V2���pL���
XՒR��/��U���27d�؊�7;W�ؾԘ���j����.��&�~ef�]�p����2e1���<_�dk�϶��j}
f�7œ�W�Z�ӽH�ڍ±��Kpn_0�?�����E^�д�	� ��8� ��ݪ���C��!8��0� LEq��2l (��l,���;�v6���*���	v��]9��	�ZK]�Ȋ��|��C�R�O��bз�Ŝ�an��D�[
n���)؅�ބ�/2r�*�щHwXU�����R��S�7�1��#����$K�8�r;"���pЍ��*�{�\̆S�-$Ja���P��M�g}�q�Gk*%�(�
�F������S�����E(Z�)PC�B~�u��5�b��Aʠ���"����^%�kC�̚F�Y"Zv��h55c�A~�)���Z��I6
��h9ŪQҍ����PM0������
����N�L+_j@���vc���KU3=t���g��v��qs����)j*�����UO�܀vAә��
	
ソ���$����J�v�qc��}��Z�A[�X?�'Lk��q����ǩP^��F�iD>�A0��51u��~�tDMҀaq#f���T����ʩ'�&`_6��R�����3�H �_���k,���7:	��S�!^��1��V�#;X�A��Y�/M�����	B�>|�q�����O����YvT���Z5`1(ń4��T5�<�󜢤��X�Cj�XBE�`3w�l731�R,!�-E%��rM9���_O�*�P������a6�����f�xԗh��IX��5������)j*������(j��ꚢN��e]o��n�����״��-(,��)�+F�����S�|��͑M��8ݛ�U.�|�;�›|����][C�z7�6u���w=�C�����]ܳ[�����b�ڱ���
��뻑ΰ��������8��6z:W9���}�G6�]_���uC�4C�
Ӷqy��i�~&�F5�آ5�U�fɀm)K�5�R/��Ue-뢤��X4�x��^���V�湽��]�������`F�_e1�E�$�sI> �gp�W8���XO�E�x��J+�'�Z�EZ*[�g�I`��
���dFX�i�b>;5��4Eձ��?��֊�Z��Wy��cS1
k8JR�1���)��x��貎U����j�<3�o/�0 �����0���K1O(QG�#�]<`	a�h�0�}�u\�$E�)����ZLB�A?��EqL����5,ǧ��ly2O�l���&(�������X���ڨFɰ�ި�Zy��g�ZFe�c�è��1�
�w&���zI���Q�8]$�>�Ij��ëU��]�Z�h��҈����4S�X��{��15�r�d�ahF1AC*������(���y�������pqtb,~��KB�*.\T*��5��A���Q��b�d'�6@o`iw�p�iL�Q��o�Ѹ��V�2��޿6�W[�t���eR%l7��S��qE�$�/�	L‘\8�5UӤ�	EPԏ�y�c���v�>��Y�?�� ����D��8�'8���Ŕ����,���VXMqY�l����7��t���y
�J��hZ2�����&Dބ�}~�_~VK�S�X�=�R;������~T�N=+��=zɾH-�ȷ���G=U���:8����!�Qc��s�Qb�Sw@aP�5;s��O�<�S�e��(��8��
�(nK��S�}�I
Z�+���'���G�����#&���8��"8}�?��������^�x�z|$�]��vbp40	�$y`����c��G�����f��ϓ��� �9X�ߝ�@h ������N���!٨y4�;5�x�:�PQM���IU(�$At6&��,��Dn��qP!�-�q�,�n����V�1,�R��n<���Gr�r�e�v��81a��ٲ�X�L'q6���2��I)�e�W�X2Q)ɸ�b#i�\]M���R�W�ˢ�x@B��Td���U`vL����L�c�	rtZ�����I5IL%�#�3'%_LN*����R�c�dn��[&�%�?�b�u�����d|Y���n4��۷z+�?����a�^[�%��]��
�I�-x3o�V}��a����wƹ����f*���	$��x���7���o���Xf�h5�)��MR�$�ɒ��:
c��p�2F��܁|��%K�D��y�>�-�����Ih��l�VA����|2���A*j�de��xԜ�q#~�#�9ȉ8��I4b��0��(�����Y1�����i����&$�;K�8��7$��M��}�����Zzz�E^�w?1���*)�9�e��(?=*�I�dH"��GÑ���ݤ���P����Q�3�����a���?5���k�'^�1����y�Ł���f#)+��?x6⊿�M>�I�r�+!�(�䚎��F8&�^�N�1Q��DR����%5��Q.ʉ�qMF�.ؓ;q1��h���z�I��&a�!EՁjaT!h��ZJ�0��
N%���c�t�� 5l��=��z O�s����0�Ō՞Sk���:^O��d�(Tbp\+�H.\!�CW��*'����nD�繽����\0�g̷��o�
�)j��������)��X�� u��D#oh�F5��W��"!d�iωB6�f�Yb��J.���i��T
�6F�7֯�L�P~���Z/�U�dj�R�Q�e�h��b�
�R��LKϘО٥��*��9I��Q�+����bTcF���%Ϸ��2q�V4��03`���Q1��4�L��j���0�����ǘ�N)��H�P-��B-M7�ʀA�~�-{���N���������p��<��-�[ ;�����.fo8�%�����r߀�qk���<b��eȅ솴��G�/����=�~�d��(9C�\��$�@'L�`��*�2��#���gYѺ���7 z%Fp��-o|�s�}˥�v�d�g%�ğ�ÊC�s<�#�+ۃ��\��p�#�;��i/���۽�WDa��8��s���[d�����v��)����FHP@6%&� �"�����q��0���s�&��1/�/�#=J��A@�#[O�Y?�0ǡd��`��u{�p���<^��a���Xi���a�z���s7c��KX-㠟�/����
��ky���;�Ċ�W�J����j~3p�q�^oA9V'�$X������(�g���L��ٌx|�~���s���� Wf�_@�p�;���jg�4�N������I=�d�<����_nÙ�s.
h]�Z�K>J:��e�b�2Ԋ��q\P���'�b��D̴�.��lE����b�1ВZ�.P�X^�y�$�z3��֊XOh�;H�ؑ~62d����g�v�c�-�E�#������fCE���<��X��/`m�j�&y���Ù�+ M�by	�pu6̩J<�ŅՔ8�k c�����Ɉ7!�5����#\����~�j�i��0R�z�x���S��,���\�vE�U[��N������-t;�f�
p��F�BQ����<� ��j�V�'�Z�M
r��^Þp��7�T	YI=�JRM �g�Ul�hK�x��f�BOc�E��PEC��,N�¸"KlW�e=�gíp��D�Y�Y���\CIB�İ��O@X�:�x��X,�S��ߵ�Mk5yn|�C)O�u�:�P����Ӌ= ��Z�������W;Z_�SOP���L-NY�V�b+'�.��za_��*1I�0�Ħ^�+Ja	�\���BXL�Sԗ�Ȥ@	�8_��iOi��PFI+���u6`+�"�Φ�HN��
�)�w����.�)[5ζ굒ԁPQ�5EMQSQ��1�wfu�����t�<=�Hx3�xMPG�?�a'�'u3��T���G�)�kc��8�m���[�V��g�'� �H}5EMQ_�����,6�}!��Z�L+,�F^j�G�Z��Ƌ��4�� 	(>ު(�l"`w|䍼���YS��z�^+e��f��JC���46��-
2�G>$e�|Q#�W�0덺`�{q>�X��Cp�5k�����ه�)�z��������N���8
AZq�={)��Yd���sN���S��N��,x⏖�\�y�f!�Y>�V���0����'\�@�
zz����R8�;�s;�Jb�N
�ó\	x��H�e��Ͼ��x?�$�#��Y�e�g�\����1�w�G�>�}�P_#�jsgW��穯���)j*������>8�-Gghq�����|m���J�a��Is8�Ǧ;>��.��[��<�)�MP�WO��7wg���>^�ܷ����l�U~ �G_x���zV���ە;���go7���j��Q����������)�(�=���8͘�,nf���'Z�:�*5EMQS�T5EMEQS��%Ԫf@>;�q{1/sa��D�Ux�J��	z��m�7wr#Si͏;�E��ì�Q[hW�?�D�E�`FA�n��I,�f.,E�Fe5/���a��©q�?LH`*��"#Y$�dxE�=�a���Y��-���gn���ԁ�eO��pA������ �/���֮n�O�� )�%<5�8����r�/>�mz��2C*���g47nO��������q~�U"��u�ħ�:�ס�K��0�E]G{�.����?��#��~|6�����L%�e�%�i����i%�u�����1Q�Tg�����RJ�~�H-������(\Ij�w6n�ٝh
�����(��赚�C�[�G���{G}_lp�֐�;����8Y�S�l��=^��+����w�;0]%��E��.�kCWv�����-�_��M�8�Av9�l�n�q97�9;�r�{���`��,�4925��gLe���jQa�1<�_��cY�Eh�xC������
<yhif�h�^��1?�z��k�9���Xͨԫ�VJ2���i��Q$� 	�>��jϩne�B�b��
�d+r"��M�����G'3�wh�a<�d��nO�^�ۋ5fݞ⽞o�텹5�����޼�OC��Y��H%I��}`_a�8n��7皪��iXZc8k��nԧ�`�3�5��RF���p5�,@�z�� �Q4�Bq��.{\n�o
τy6 ���a9�!>��xIQ��!!ǎ;{�nS��Qv��y�?��b��������7f��#�(�yeM����g�#N��x|z�a��8��֙�Hq![>ʱ���2,<7孏�Fy�升G�)`y)/z�q{��|�)��dY��9��+:9465�>��f�D�G�!�E�/;����͟j$�?���������Y%��Q��t��!7�4�E3�����A����{�ߞ�v�ku��@X.G�����H-w��ȑ͒�t{eG8�.�ۛ���"r1��B@��#_'�
v�s�ń]�f���}B��Ʌ��>dU t�+��y���n���bk���vW���t8�'��)�*�kRn�b"���x�(�` p���"���j�-���|f/�Pj��(��۞ g���]hP�G�xv����-�]J��9�Yj/\�r�MH@t�<o��sO^泰*�,
L��C��[��FkO~{)'���م۹�N�l��{p��°	��B�l&�sKkş?j}c~OS�j^�}�|�כ��Ip�x����G�	{��L\�$ى���Xt85w����)	�DR�PLN��'�PynGB��$�SH9�����%6}Ԅ�+�r#�ŕ��:��m�tL���`Y^���,�	�"�7.��n��F�Z�o�8�j1�kf.\u��f��7d%P�j��(q�$��P�bH�@ �c3a��~^V-�B^�C��]>Vj��Ɔ�;f/1<:�r��p��DK�cF�DGb�χN���pg<�f���;��8���ݣb��#~���6+���<b�?8��>8�v�r�W#C z��e�/�^���<+���5�o����}��GH��|g�{"؝ _����H�ّ��+��E�/5���G?��P,2$�_�E� �Ar�h)����eoGj?/��EJ�%���c��Tt�^3#��dS��F��4�>��RE��K%l��%+S�R�n����6�&�TM��hZK�U�kXJ&�����\J������YJ��ܴ����0�T\��֬�I���zQ׋��H�O��c]I*zFSt\E-4S��18�)�q͘�t�Wb%-�uȵh�uR�T4�@t�lO4p������SV�};�Ռx��U�U�B⇂thӦ$B1H�@�3[�f�|��䔕0H�o%g6o�W:�o/Ya�I~�JU-M����e�^E
JvNՆ%�DV
��:�H�dTt�ع���|�U���]8�\$[�y�ʓ,�[+o���V����C*#�IPѨ@
���Ѱ7:������k��~Q��5�^��
�t�'�����h<ҽ���T�M
��k�3����<����N��מg!��D��SN'���Zw7�H�|i�����N���Pt��}�
��bsdg�q17���F�D�G�2�)�3~�`�����0"q��/�G�ȫQ�?4��ؤ�Cq�S��O�$�f=��ߣ����~���^G�b���1���k�sfM�M�g� ��9I��q�1ldsH��çB������@��K����s��p�����d-z�h������0�GW�W��˴e���QQ�5E}C�^�+@��}qI?Ly^=���8����{̾��v��~��m�o�\���t�ܶ�>\�P��/��\�@���7G�y���|.N�8wwwx��A�^�d�$A����+e�>�0��>]7�jјn�>	״X\�d˼p��v���&E}��@+b=:na=�Ak�VL�S
.�*`$�T���F����d�z�58q�IQ_�	�n_n���F���ϣ�o���'�e��G(;���Fx����`w7���T�<�I��3�|Rc5�
�(�zB�h!
)ĦU5��B<�p���$�.P�WM��-*-R�5E}��Fkz�2ܰGM����4%yխzK�y��D�C�/%Y���{حL����8�1ez�P��ӝ�2��2P�Ą[����=�lMo����ӯ:{(ҫ�Z
�b]#[_�Se[��<��+�����5=�Ԫ�U��\���赭��N�laV�z���wr�gs��&�Y{r�����E0��Mt�Qv7����\�?n��D
܀�DWD*G�� ���=^��0��a�W���bd2��q-�w���;�D&>�̱���A.>6�ͺ‘n֟�'��a���+2�fX����?��� ��SB<&�X��g��	�nJ�/��Rx3</�<�$��/�J>#����b_p5�'�Lx���|��Tųg|����hHds�g���o�`�m?�o)�Q�>�� ��l9=l�D?�&p
N@�h�8�I�!���O���T�p~.��9w�5���|3�n5
k̪`�`h���zK��A���z�JY��C�
����1�j�Z�F oom�XPlP�Xq��4L�4
��[��$;�����zT�*�ư�<c�C
�f�(�=�O�y���7#j*������(�$j��܈=q	\f�1J�Z���^/��Ҷ�7y?�l��r����
�M�O�h��յ�Π����\��^lě7mc�]6�K[�uJ󪢞%�`��!vPa)ХYǦ땺UU���7j+Z�QihV
r(��
�p��۳�Mq�^@��t3�	��3z��*���D�D�:?а*�.h�T��V��=BT7xAk���(�
Z0 ��-�l��A��S㠥GH��y�hO�	))ݞ�!�@V��tc�X�L.�T�3��S�H�$��7�Zr5$[�8Tc��̍k����'�Գ#�x����bfZ�two��n>{d����χD>�L�s�Y_t2;�t2�>2ˏ��u�'��x!��f�
j݂�9C>`��nN�ٗ��
�ͬ��R���)��7�����$�Dn��8�^����vTBjw��	�%���^����j���^�exFE����q�iW����l��|
����l�8�G�]'V�Jw@H��K�Z���X5���M�@�	���
w�;0�ž���1����8�3^�
D��#�k������fz:�O����o��8��0��Mp
��)c9̑Mܔop|�<aϑ�O��}@UD�&`b���<�R�ɕ�"�����%����[@���8��ѽq����Q�Po_H���W[�������x�6]A���a��ո��N��zAMEQS�5EMQSQ�5EMEQS�T5EMEQ_Ǩ�����7t{=���A�;t�����qP-N��K�ܧ:���[�W��E}��"w9�.ǃ�{V��}Z~��m_�������
���ܧ6�����{?�}��{~����u޿�����/ܿ>�����'�9�a��~p���ow	9���<w=�߼�}�JQ�w_���,Y��(���Xl?w3��E�����K.�T�/̌S\����tD�O�?c.d�^��}��t��������Ic��gݺԵ��h)�V�.�u�}aͷ��k�Z$�[C�����c,1�P\A�1�0 ^�ē��X>�J:2��8`�A�G$ad2Na�S,��HecH4��
J����T��x^�ӵd�M�n�U�b��9��܎xRw@L�� �L]�c�C�+�Pw�\�:L�)!5���)I�j�OǦB�'&3S���P�}S�y1����Wm*�Q��5Cj���!��\���/q���L��+��b=|�^��!�J|�
����$�G}�r�DyExh����tm��p(�>��9���L�FI1�P�/��PP�1�wn� ĀCSOy��7�({jg]O�����.E���{��)縸g�Q�o�>W�<=q%԰=�̾��S�lOxq�Q���?�E]W3'��IK��%�oT5�g�*���.Č��dk��L�$��X��	�֎�Z1Y�k�pANdRZ��M��V7g\h�#�M�#�"&�IL6�@o���V�V��K�l%4��^O�0N7�(zI����T�2���zE�KPLq?n�`UK�J�$�B<�j:4�銎55u�8��Ui���hu�����+��~�0�8��ޫ,�����y�E��C�>t�������͟4|��5x�y�ď������?";^y����8�Ӧ��W~z��J�G��+���P
�8?~�'�i
�m��<:��>�?���C�������LJ�����w�Ћ/�C?���;|�ࡃ�^����j�x�����C�����Q���R�o�Y/���!B���8a��~�/}�=|�'����ʼnC�$�+�+���:|��=Dry�/~B>�(�wqyy���G��~��4�r����Ϳ;����Ņ��C;��F�������(j����X��`�2�u�5�-j�m#�V2��߰a�C������Z_���n�S�n�]��t��q J�d�$�S{9���(ԩU��Ţ��_�٢ԯ5�(�`3��`?���l�0@�^u�=����/�v�� pEW�6yKu�Q�U� �̡���āFYB���!L6E��h�����(j���C]�\�B�دe�E3Tl$��{޲qQ��/G�?����T��S�e��(9��Ժ��#���lz��4a���]&��t�6lb:Ǧ����D���C��E����	��7N���зGn7?^��K�g��`96>��ѯ�eX	����?�������M|,�kGݿ�#�;sw~�]����0E��zإl9���}z�7j�i~�٧C����}rw<��Wƿ}�c�_�<�ڪ�Q���\O}eⓧ�L?����d��Sw>~h�Wn���Q�`�iʕlYN�`} �,S˟��PU+���*����SJA2�W?��^��V�����{���5*������)j�+���i�ia��Q�Y�8́`
��,�2(�ZZ�K��Ie
�@��1Mb����y�uRu�[ʀ4Q4�$Ͱ��9}"Z)�if�
}�x��
˗2fi:��LZK�o��5�F2�8I.���������<��1{��]��)g�sa�Uif,�Y*m{r[��a\�V�-���I��Xv*Կ��	�=l�{fKU�>�OO�\��
!>�o�@�o�gp��>���ܳ��	��憿[z�=��)Wܜ
Ů�s2��������M��C���g8��Ͽ&�00�S���c,��~�|��@T��,5�&=.Ht/D4�
��)gg�q{�YDL)����EB��E��D9_�j��ϋP.VF~�Y[��l,b��FW\�	���u�s�~�>/�� a_�����{X)�^����Y/������!�
�YgY���'�"�q_<�"v�k3�8�j�a���E��f}�����kSl��+@{�Y���S�
~��������}��ڍ�g��z��d/��ŝ�ΎV+V.�ʰre�o0_MEQS�T5EMQ�������
��)��s�pp�%0�:��"U�c�����Yc�fZފ��H\1���5���x�U �jE8-r5n�D�v@D�Nf
�D�B1;Q!�n"�}�f=�+]XjX�x;��Y�8 $�v���K`�*l���+p���x)�d��Idq��i"��a&Ž,?�b{ܾ�x�O�N����������J���Wy�e��$�r��	�t�=�~�9;�@�ҘIV '$Wr�Z5�~”���O�@d����>������5�������u�Ys*���r��&�I/H�	�?&D|�88���CGR�Y�(bS��I@4��v@4V=��<���hhl�G��xZ�'ad��n���ש�>? �����J|�|5EMQSQ�5E}�6��f��d��S!c�2P�hDj���ŨG��z��2b�����Wv��}�S/U�FӀR�^Q��Yy#cRԗ��S���^^:�!���<�#'���#LX�	%f���Իy!봟��=\�o�O��S�.!
:�</�S�F?W��/���0��=���K3.>���~v7�uы�u�x6�xA���5s^/I�v��^:�C\!2�
�X6�g99$PX�|����N�?(6M�E������)j������CW\�-��K�(����{F�E�;_Mܯwy��#kf
��*mvl-t9��m{<��ۿ�Qϖ����_k<
_{��[^��Z
n�S!h�;�<�q*���Lo�'�˄�?#��7�Ѫ���O���6o�+����s�X��b�G������?�r;5jմX�1Q������h:���ԛ�g�V����p���"Թ'����RϽns�7
Q��u�Fn\��V�6]��Qn{���;��'���'(�����TAk0
����n�)�Ӆz�b�V�����͇z�������=�#oX��j��(X����Q-<c��fI/@+ZN������&5
��O����ۢF���`�s:�`
�\3L��~���&��9X�^�.��Yv��c�{��z�Il�/��E��G���g#��H��

�z!�� S�:}A�/!&�`0�|x�B�1���a��B���y�\�)�w����깪!��h�HQS�T5EMEQS�5EMQSQ�5EMEQS�T5EMQ����I�S5����P����X5�ɖ�����$�-��E8X��n�~�P���1Z)�bO��xW��8�%j��tx8�OT�lq�@Mh��Ԥ?zҩxK	<���pj����o,
�-��ng��X�o�����5�j7��~VTF�E��ࡱ^�eds�H��1��
�8�����F��:�F�^[b���F�*�u���4�1mB�v�j�e�۪`5o*�� �g�q u��V��i�r��W��i������)j*������(j������)j*������)j�������(��J�?���5���IEND�B`�PKEGA\|�5ׅF�F5Pictures/100000010000030000000300E4B9002A2830C766.png�PNG


IHDR���	pHYs���o�d IDATx��{��u���f0�H�Aɖ��ײ�ݬ�8��Y;�#k�i3���$e�V�����������,�"@@�$:�`�{��<��*��$����Z�k���~��cf�+Tݪ[���E�3���>3�U�����}|�!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!�B!{�ܫ}�A��8r�\�B!����[R��6�v̓�3?����=��B!��WeO���Ԯ���jS�9�<I9y������~�!�B���%�M�o�C�ؒ)�r�ٓ�����	�G��S?a��j��A�d@'�B!��B�ڎ�7�H�[��fO�@d��5��yR������m'�mG7�[�<f!�B�cK�ڒڞ��}Ae���M�o�;rOdƿ���mɓ'O�D���
Mu���WG!�B���D��H�ɑ�6��1���>�@r]���6�|{�	�w���%z��S�'i�4��������^����E��N�~-�{���0��	0A��T�B!���C9D��1�6`��^��^���_��_�#�������v.}�s��^�О, �I�!������/P�E�#��	���)����c6�[5��ߒh!�؃�B!$�!�Fh��E�I�6���8���n��Ц�@"	
r�\�{ �v�H�8�f�G�i��4��=��|��H��8�'���	�!tD˵B!��=���;rB��'�/���܍t!qI�i+�!wmm���D������m�8���VPF��!�xŵ��	$�B!!���!�w#��KX����=���(���ݤ�̮�w���?R�1�0����$?O!��#�ҳ�1�Y�rti�vH� qv�'G!�r'�)�@(�AhC�!��k	�ɌeO��G��g��\��$�,��]+��@�Vk
���������W��ٯ^��F���SSh����ŋO8�qJ�
("��tm@�.�N!�B�� C�3�P�#��D�W<K�
��Gy��Ծ}X/�028��^x"Z��p���&��v.�k9��٭�<�#�6v�y-�ˎCN��ϟ�V��V����������0<<���q�����ŋ�����8:%AR$���6 "FG�B!���c�"4��i�B@���<���SO����}
�z�F��������gVV��[Y��Y�kH�-��h/�V@0��vOt{�sf��z�O^�~�J�j;;;������ ���011���	LOO㳟�����rn!��:
$��PD!�����K/�	$-��e�-��}�[+��(��h4h4r��8p�8��^z�:�C���*�Mjv������	�h�_�~�������Oܸqׯ_���666�j��j�088������all���������.^�����2� �(#-	j iJG�B!���1�]Z��H����g��o~�WN��_�%J�677������-lmm��������P(`zzox��v��/���"B���H%�TfשFvkPI�Ȕ�Q�Oh�#G�|�X,Bn�Z
�Z
�v�v�|�|�f�Z
�F#�yxa��.��8�*���7���m�Bzjp�B!����b�A���Q$}�����ϊ�/��ͭ�ET*��e��u���XI"4�MZ�����0¯YC(�I�y��@���&{�X=�Y������܌������Ik�Z���f�z�j�R	7n���~�k���Y����n@��g�F��FX� ����<�B!�������6܇$��D��F�������y��̬\�v
7o�D�T�����:����ZR}��ڊɛ����>�`٬=�D����ݘ��$��K���իN �8m����j�������m4�TF�^�cyi����_6`
�<]� �V�r�r�"	
� �1@!���a$?��s��G���޽`��X�U,�F�ZE��D�ٌ��ڎ��6���|�6	3
�ϵ��߻��~���5���u6�nt��'y��������h��B��Fxm��o߼�\.� �n�-X�I�N��kfffurr�.]:��
qю-"I3�Cgm�	A�6�B!�e�a�������/~���}�����\.���eH�H	�=)v��v�om��n�����*@T�+��s?� ҆?3���s�Ov
y���c�_?qR?��A�z�K��~�駟�g�<s��pk�Dh��4)��6 @��ŭB_��	!�BH�㑄"��F������t����ųW�^Mi�k�Z��6�hw�*#�����ۀq�G�`w:�IP��C���v�䵑ht~�7�׾ ���r��	����_�=�y��?��?x�i��F?� |!�C�)ha�����(�몿	!�Bv��@����!���G7��ͳ܉�����r�����~�����VGH��vz�*��]�ݮ6�����)�@��,_[�z���l@�ݎ3�f���qȻ����B�.]r�z�z�e$�)�Й���8t!�B��$?��S����k��_�"�������u�ŸM|��D�����A���ظ�{t!mec��#[s��u����b��Fg���}C#�o7cGA�?R0A����;y���E�=L�
xIE�0BI��,@�$8��
 �BRz	���Z���@h�O�ݴEx��G?z�T*�R��R��2o���>�A�b3��?���������9yRs����&��)����P�^���߿V(p��_6�<�V���u(:U
�������	!�B^	ZQS��Z��ƿ���:Y,ϕJ%�J�X򳽽����W��^Rd��8�\;�l��^������+��E����-N��
o��l�裏�<{]�i�� �XG�AXPG(	�k!�r��a�K��q����滖�����ܚh���j,����6��O�Z-H�����Wv��]P�jRۑT��V�.1�}sfffV�^|�ŧ<c�I���T���

f�X@!��;1��B(�C�׽��Q������bq�T*�Z��R�x�{�ݵQ-�Q~��Q�m��4�v���#��y��
����
����>x��3�8}��.ta6`a
��^CXЌN����Jf!�ҷ(��5����dt�\�rG�ϯ^]_�
�Z����k%?cH�}����+}���5�m����h�?@��ڇ֣L��F>�����F���g�\�����%�/�!����Im@�,��B!��f��txԒ�q$��3���\XXx�X,���gss����'إ;E�Ek#_���?���#}��O�X�9u����� @SM�VQvn@���}�ݷ�������\��0p�|�3PE27�U@G�B!{c�K_�a�v�~������$?��KKk���(��������<:P�{j�OZ.�x��!}�t���}!ȓ=����)_� E�[[[h4�B������._��+�����
����6f!���qH~�S� �󒨿KV
O=��ß,�k�b�j�j5n冀�bA��~��&}�v�֠��[��8z�\��SS*��/]<"����������թ�)\�xї
XE�
���PCX �m�B!d���;����nHw����n��?������uT*��e��u�j�X���oN�����9{�|>���:�����T��3��]h=�O��H2�%�^�c�������KK�?y�/"=AX<d�Uv��� ��	 �B�nǣ�ɏ���V���^����>_,Q*����������҆�4�z1�����S���]��߂_ӥ��
m��!�E/�\T' .6otfff%�,#)֬8�d�����ۅ6���k!���1�������c��񗉾����C��.�J�K{�j��F�K~��E��Y"pW�_p)A���t��Ӑ���y��g��֋�O ��R  �%H2O,.�:������4���H*�[Hר�6�B!�
�`/��d�{�nk�-��ͭ�E���T{O�Ѥ
��#�h�2�{_�[����=��`EiP?s�o���X&T��5AX
R��&���w�LMM�…�l�;�d��� \C�!h+�����B!������.?b�H{O���.��ϟ*��+b�K{O��':?�5��
|�H 1�56p���U_:�9�.�O��'Y�H�P$��#ݙ�$�%#P�����S?u��ӎK[pɛf�# ��P$�?�!�����!T4�G"��}�q.,->����k���*��&��&Z�Vܒ]n�i����X� 0=Xo��g
�ޢm~�s4�ӓW�Ձ�}d{�+;��&�����Ɵ}�˘��=}�ʕG�w\���]D��E?7�Ln"t�H�݂!��}���/�='��N�_軼��p�\.�X��^O����?����YO@b�혓���q�nP���n�S=]�(���+�j#��PT�]�����n4����
�n�O")� |�j�ChF�	��B!�|�A�/�=H��P�cO?���W���=k�j�Z��_������G��w�2��M��=�6�uoM�$|��N��9�M.��­�2�tm��Ԏ���ܩ��a��7����Ɵ�/!L�m"�TCX�D(�3�D!��W�����b�K{O��K_���%���=_*�P.�������������#z�{��DG.J}���6qɻ�:w}��j��Ӈ�LYg��ZJ��Q
E�*  �
�nA�F���j�P���Dd�k���o��!|cUf��m3zH�h��B!��W
?Ւ��H����g"���_��S�|�֭[�V��T*qݤH~���5H���m�-�������΁]�s�8������,���v�@��&���ڀv�{����}���E�=�߉~~�����O�ؒK
���B!�e���b�K�r��׽���z���[-��q{�z����S�7�u/6�3.е���Kʣ�]�l�@ֺ�B_:�@K��w=�6��*���꘻�ע�Bg��j�&K&�V�afffmzz.\8�f���%�o>�������ϯaB!���8&�"^*Z���Sp�4������r��R���� h�ݎe�"�ټ�M��G���,�e��
��H����DG�/?]/@�I��"H�x�� ���@
���-/-�<���&� )E�X�U$L'�B!�p�D7X:�t{�)��
�>��Z1��oll`cc#n�)u�b�az{�c�,[�.������?�?!}�����ζ�ۦ�wU�~�:����:w���`�v%�'7�M��̬<x�ϟ���{³>���)�7t��\r��`B!���"T�"��H��_�§������qbaa�d�TZ+�q{OQ=���Z%q 2��1.v� :%<Y"�إ�wv�d
����
�XK�t�nZ��9^�H���@$
TJItoR�;;;����?�?����څ�oE?�"���Sב�0@!��C�/��htG���d���裏�^�z5.����jqkt;���A������o
yW�F[$����6��
�}��1�B^zگ-@[C��
����ԮwO`�=?�����������[[[�|�!�B�p&�a�p�Nu���@!�����_�{N��O����?�L�X\��=��_�r�7:�%񱅸.�Mo�?�|�w���>�s�kĻ<=�$`�_��9�$���׾�����6 �˥�
�Z-��/���ܹs��c���B'@k�fj�mp^!�rGc�#��#-��N?N5��/|����Y__Oi���F�EK~ޠ��muD��^�o��B�n��}�z=�_�K ��{[y���3�d#�0�|�AN=���� ��1T��h��޹��>������.A@�<��	�>@8/ @��$�B��pH~D�/�=���YMI���o�ݺu�J%��ӥ�����z�w�ڣ�RW�P+�s2�EY����nﮛQ//W��K3��Y癨o�"��:`�����=Y(����+~��ݲka@�l!|���@!��1f��K�/�=�D��<�?t��s�RiMz�onnfj�����6(���}}]|\k��E�w}��9@v���w���f��o֐q��k���A�o)}�H�dJ���677�����?���+��K�����^��� ��	 �B�����E�r�:ԫT*�T*�Z���{��Gl���0V��\��e�gwI1�
����}��Y�������PWt0v?����d��`�z��v9��afH�P��܀��-��Ξ���ƹs�~��`�
�ǑdFlD�Ftk!rX@!��������mI_��������\.����T{O��'�Wo:�r�"��ȶu���-.�e��φP_:z�u���V�gmG�}��}�ɏ�` ����z�����Z��F����M��u|hy�w>~��q�ߴ�B(	��CH>�P�����k�B�#p��n2Dt2��nk�-=|�����uT*��帽��4�_"�oFg�T.ƶ��q��B�eI�;I��۵�*>f
������#^#��z����r����7@�k���o6��.A�v_��������~��~��i;�A�����0#PC�)Hj�A���B!d����K������:�ֳ������r��"��H��u�����/`�5:ت��^��ۦ�~��!p��N�>�N������SEz��ƕ��}->�v�!��5�{�['凂�>zCeu	j6����V��~��o��S>�8�*�H�@R��kbv��
���!����H~���#��L#��S��g��奥���u�J�T{O��Ksm�g�=�H�짃������zr�n�^C��;>�\�`o��椏�~�]2 {lV��N��j[��� �6[�"��@c�|�|-vp���S݂�6�_��������/ -D��Gf�m"t�SP�X�B!��.�����Dz����wyaa�T�\^�E�.��6���$��e�i���֋߷�e�ٵ���'���5@g�'��[�ߋ���|΁+{`=��k����/�2{ IDAT��7��@�ZK�n�rK2�Z
333���Ӹp�on��l��V`zn�u�i�B!���/Z�Q��>i�)}����'t���˧�^�
-�����%:�
.����@m���#����R`��k���X����qY��-$ձ��d�G��4������7�60�V;q\����4�M<��'?���t�<��PA��v	�Fz�0k!��W3�K&�!�>G���$�}���=_*�����ڊ�����;�G��(��$��.�]�� �jCg����֦�{c�ї����x��O~�]E-��>O�)î�ɕ��s�`k_b�[���E�W��P��q����
\�p�I���,�<��S�Dtm@+�)����!��+�H~F�h�ǐn�Y��6�
}����[�n�Z��R��H~���G�9eWK�
�;�W�wE�]������w�E�v>�b�.+�M���/�nF�%��/��؞[��7��w�߉H�hH��o��@@��������gϬ�-�8�P$3�H�m"��	�-��
 �B�_(�_z��/}�'������DC�d�o�R���Z�#����8^ߨ�k9�6ށt�]��tɄ|h{H�����Y�k'�v�C�@_:����zQ�
umx���p�W�n��#b�@"M�݊~8�W@��k���������h4�6`�P(��_tu
I�Q$�$4@(bm!��}Ĵ�Ԓ�}�1�E�?��
��Ʌ��g���j�\F�T���&677㠡�K3�{#�?K����}���]���vsI�\�+K�CV�k���| y"y���~���v y!�L��:��̾��$���z�M
n��q�@�6@2Z^��?^|�]�z�q�N�UF�v��B!�{�c����^��t������O��#�������\.��=��f,��������p�A_9�v���v����v!r[�m�e��#}���mg��������Zyjy�o�]۾P�ӗ����rA��R�@��J��G>��r��c�G'�᱄�܀���&X@!�|?� �t{�q�F��]����?�L�X\-��V��V��J@��)q�q��&х�Z��+�����������u�]�ʩ]~��}q��5{�!/�|+�}����x}�}�qԶ��^��1:�}���凃
Ğ;��
�6���۸������ƥK��8�xx+�:�6`�ڀ�B!��ˏ��H���Bh���}�ر����q{�z��Z���@l�����f<��YA������w_;��M���Z���و�K ��wD�}N������)�f����U9��|����	H�P�� ���nn�bo^�nA�Fsss�/_����ො�~.�sn�<$�
h� ��	 �Bn��G�}�I�8ɏD�}}�`��}�J�XD�X���677�:Am�������%:�n%>��i�]���N��^��Xץΰ�m�c�9#��[�*�q�oqe��b�Q���:#`��Ul�b�����j7�����`{{333+SSS�x��2�_���l�L�"�
h ��AR@Y!�����?���tt��|��?�O����+"����"�ѽ���#������r;|˅�������e�Yۧe��2�����n;��;��`�>��n�a0ۭv߮����]�Ϸ�=V�5o@�}�� ���yA�$@z����ϟz��E_6@dB�!=7@�$�
�B!�8�}���(��������{{��Oߺu2�Kfى�������o����	��U�θ"���Go�R#{�=e���y�1��S�����6������s�?H�j�ϳ�疵E�ڻ�}����l�U��8��P/d;A@j��������G��~�#���P�B�
`m!�b0�=���]~&��D�'����>��R�tZz����N�5����$�����O����`���B`����]���������x'З���_,����d@րp��s0�y]���b�O�s`������m��H�'޿��%�V���h�^�cyi�S++G�4|
�SH�� ��A�$�
 �Bb<}��H~ƑL�-�ݵO8�K>x����oll��~�V+5�wxp?��l�5�p�>|���5]��v� t�$�v]����Nk��jo��v�50�$B�
��^&	[t��'c�e1d�>o����'���H�����SSS�p��	t��p�0�}ۅn ��ڀ���B�d2i�9�D�#�_���ϕ���r�����l��6��t�,�����O1᲋���H�/��߮zJ���~����J�F_:� ��E�VS�GZ�j%B�%pIp��w�>���*�-v?���{A�<�?S��%Hj$#���哿}���8N��I���pt�#lj��#!�rG�����g��G��Y��G�>����|�;�T*�T*��j��jZ1�ߎN}���Po� ��"�����j�ϕ��R��3頯UgX''K��5{��������{��N���2	X�s��̪����m�_
A���|IC�o6��.A�v������3W�\y�9ǩ��~A�],#]���>��	!��1x��H��G7��3	�`�'%�_�T����l���oW�"�Y��}4Y�t/�}���o�]����W&�%/�w���5���O��� �=��r�ls��]/4W
����ǑU]/k[�]��� �
е�f3�x׻�u�P(�ҥK.I�"&��t&`� L!���%���=%���g�'>x�ؙ�����_��X��D�{M��`��5:3 ��Nח|7ݾ���������0��/���=�.��O��x�z�2�B�
|y��֛�cV��
�����ڜ��U7�����o�F-�H�Iv@���͝�|��"�
�#���%�%A�M$��:�B���@�u+2Yi�9����� ��GgggϕJ�X�����i���:��~��j�e�v������K��
mK�q�s�����>V-/�gC�/]`
d���mt\o�!kWo[1�u�IG��Z�E��m�X��/3��dh'$�:�N}�.��V��H� �p����
_�0�G8<lIO�B9P�d��\Z?��!��!8���
��6���D��:Y,ϕJ%�J%�j5lnnb{{[[[Z���t?����{��8��3�����>�V]���mV&�%U�
�DZ`c�T�������}\i1ٮu���@^�Z&dk��u.{-C���f2|U��\��"x;A����A��->|r����8�P$� <��6���߶
�B��d�#H��H$?S�k�`qnnnM��W��X�#�9m��3y�T��Q�kw^;����܋#�U`l��[C����e���Gk�׸���2�+}����TA�+ʯ_p�(vE������[���0h'��Z_�B�jIj�N�,�d9$G��Di�����	�.A333��B/�����1�%��%$��� ��U�$jX@!d/#_�y���!�r�1$m=�ˏ7꿰�p�X,��J%T�UT*�xN���NJ�?�2�5�踯&���mt^���[�,���>�~r���h�����s@�a�_1��No��n����H�i;��Rn>�C�Y}�F|�/t;��~�'�m��s���H�$
��O<�̙3��a+�#S�������&����N&��PZk�K{�I�����X���C��_���Z
�z=nխ���\?�n�"ؽ���}��\#�BVfA�;-����dCݮٕ��c�Y�{;��~�/�v�����4]��+�����E��{u��X�_g#���Qq��������lڑ�� ���8�v�|�V+NCJ��F����ٳW�\YDv����!���IIm@�,��B!�3�k �i��8���y:����³�bqU$?��skk+n�)��T�?���ݧ����?k?�}\������Zg���W;"�q�m�Zu�'M��B��M��_K��q��|Q�>���Ҳ�uemW+Q_7"}�~CX}�˰wɇ��������rA��;�K
��2P���[{�[ߊ�~�c�<縤�~@�"t�H��j�B��_��#�^ۏP�3en>���#G����Q.���=%�.��;�6�m�Oк"�r�O�,�@K�ke5.鍭Б��Y�:#��uDtPT_��W�%�����ї��@�|��C��F�{ME����d=Y:~W6���j_��u�1���t92��Ӆ�?�z׽��oy�lmm��h��&��枻|���@X�#?0en�����6f!���8$?��naPK�yI��%���~��O�ŵb��j��j����Z��A�w�Ett�3u|+}|�s����n;�b�b�t�6��E���[���1��!^�5{��5�}z|��j��,����^��O�c_��:}W����\oBY��׿���"G"t&@�}�������.^����"�H}��
�!��ڀ6k!��8&�!��F���]~&�����?������uT*��e��u�j�X�o���P�(:�p���f\gɀ��VO��d��i�E�Yc ���.i��
������t|5>��ǥi�i3����է�9�E�}�,��K�c��k��wV��J���������0�v�c=�H�$ ]���:|���>���,!��X�r�	���ȿ`'�� ��B!�<Z��h����2��c�����E�J%lll`ss3��Ԇ�3�˥���O;�y��5r�
����:�1��lZ�Zy��i�uXtV�<�>f{
�x��1\���t��[|Ƴ~1k����Q�tnz�E�S�]�k�����F�X�W���'�����w�a�����J͘��Y���H
�5k7��y����xa&`���
��B�����B���_���F��G7������;t���R������V�h4��G�ɨ�L�}���
�m_@�$�ǻ�"��wE�]+�96�:��{<.G�:9.��=��K ��gFڻe���
`���:�Jo\Y��s�~=U�W���}=�5��O���@���މ�@��"�_�D��IF�裏�:{�3p�O�^��.`ɇ.ʁ�����B^q��d����;�0����-��ͭ�E���T{O���
��}���
��wsV�=��e���"�qU��{�]�ӁJ�\�um�<vp/�W��:J��k�0Z_o�|�%�Q|k���+ݱ?]�v4���Z���pw2�f�k�߮�j�*���Y~��T��5AX
���&���w�LMM�…�l�;��VO�ڀm�6�B�+�C�/]~$3-����'�Y���?U.�W����.�Ot~��z�C�㊠[��[�Qmu���@�o\XE����+�o٦_t��2�Z�D�v�ᷳ�^e�:ߕ��n���8�HG��6��b|��6��.C��+N��X���T��M�jW
�v�?�F?A��E�E�%H&KF�^��C�˧��E�O~�u��N q:����B!���Œ���L!����{9������k���*��&��&Z�V�R[n����	ր�2!�]����^�r`���0�5X�e�ۀ��ˬ�I��"`W`ҕ��XG�ʏ���W�������n�Wa����J����Qu�%g��>.M���׶�Ҏ�l�u�������ߵ�g���JM�s$;����?��q�~W�\y�y�%��"B'`,�)�M��;�-`m!��ۡ��/�='����Y������r��Z.�SZ�z��j��3��>޵��n�vmx�4�.�A���ƽ�@�9��w����n�|{�Zn�0�cř�����'d�;2������9j%8./����\2�O/�y_$�w��F@�o��J||��B�El��
 �9����ڀ���x�y���}��w�P(dxI����!n�Sb��"�B�.Z��s����)8rbii��ի�=��_�@gS���$��6�r�XW��H��6���Z� �+���>��ڑ�k���c��$������Ya7;��ݶ�z{�Z}�����n#�r���Z}�����>����"I���4�k}��H�.g��|�C1q7�7�k�v���Ne{6��k�H&��lq� �B��h�sH�.��$�Q��z�R���"_��_��ncVG��"�#l\�ю�vtߵ����tD���4��\ؿ}�ݷXg��g�����\�C�gح�5�;_�@,5:5k��T��Ztގ��k�_���'�љ�l��]������ؿmJ�u����������������ӵ�-��h����_-
�p�“H�~�*�e$���?�v�!�K!����GZ�a�_��L��}G���^�v-��oll�uo.��?�[�#k��>Y�q��3r��>�õ\�W�	��%H��:
���:�	�v���|��L�K�6K�Q��6�����'�m�K��m׎�\�|��u��Ƀ�r|��/�qo��.\����ڞ�.�u
>���ZGHo�,���K�������N��
h��q�Їz��K�ᎸH����z���,@��%����r'���b�K�i��ׅ������{����׿R��^�{��?p׽�����[�Y�6��
���c��Kb����ج�����-��-P���&�ceM.'�^����l��g�닭�����100 �r��m���m���6�<�fqE�]:1��wa�x��%��/B�)c񭡽���t�k����ylA_�H�d�����Й����A��$cZ�Vj��dj�fff֦��q�…pwZ8���A��9�r���H��w��B���D�A$A$��@���_��СC'����R��R�K~������ա�DƿK�����5��t����Ə��o3�}�z{->����I��@t]��dE��q�u�F����@7@�ܕtt�Z��@��M�2���g����0���188�����yܬV;������{|�k�%�i����6�u{96�����&΅�F�v�s�2(P�[O\?�_@�Hooo��h`ss�J�n�����q��U,/-�D��wq�]���="��L �� ��A^i?	!��1A�[Iw���q���]�F�=r7��������'�]���ׯ�X,�Z��V���lv��
��}�ଈ��Nu�2�>�H���v�xȚ��t��~���<�볎J��Ol9���<�6���,�~�\�\� ��~�;GFF0�?n|��/:��ۮ����~�w�7��w�&&pcdCCCD�Պ��\�\�h&�/:���$<�Y�/@[d��qE�����w��Ƶ�~CX#\���Ǿ�}�:_Z�gS����!��˶�<𿪂�v��V�wJ��gffV�^|�ŧ��z	�����M$3�Bȝ�N�K�x� ���i�'N��5-����i�S��ȷ�^u����[#�[?+{����u|_�����v_�����d�8���#�i��,������vr�����8�9�0��+m�]��r� ��Z@��kF18���Iloo��lƓfu�MN�79�o���O���k
|�]�� y�e���ng���<H�h\z9+��%��_q�K�t���7���%� �
��ꇗ����S��8븤���$]�F�l"|]m!�
v
"��~á�B�5=�Ƒ��'����裏�^�z56�k�Z�����S���:;��Ƣ�1ֈ�E�]F�/��N���~�c�%ñN��~���F������8�DAd1���߿?&''111�O�Ӯ.�"[b����P�명$�_7������O��/��I�A,�7��M_� IDAT����/T[\+G�"a����4>��f
|��F�}����ݲ�Z�b��of��JՇ����vt�����_���n#��w�4�M�I����ٳW�\YDv��d�C_�PR�8A�B�	����_�{N�ۊg��~��g���j�TB�\���&677�R�&�?� mhM���w��}\Ʊ�v�q��$�2>������l���8|_�VZ��.�����Vu����FGG1>>���I����a�A"]���#���6B���ˋ�{�����=44�|>�L����0�!�N�k5:�
o]k�7�HXֱŻz�`#�v�ݖ��pIt|�4���},6�!F���u��8^;/���� ���$A��N���܀��omzz�.]��8aa��dFT�[�	�27�� B٣���?������H�_����;����r��j��h4b�_K~~����
_��F�m��շ6��.�����?�t\�z��t�3��~���d��6�9��2)>Ń
���O�T+������0&&&0>>�����x����QC�n"qv��+���<c� ¢������رc�y�&nݺ�[�nacc�c���;�L�U�G�Q�6�n]7y���r�!�+�箏���}�h�E�����^W_�o�?�7���F�#�7������111���iLOO#cx���bt+!�
���X�G'�B�ɏn�)�����E�`qvvv�֭[�T*����:x���Z�Ȏ��}������c�:8h����>�]��}$�����ާ �#�k@��cE[n[|

ahhccc������q��A���K��D���B�b#���n�#v� oZ�!i9��r�q��?~�+��F���j��j�9�ЧF'Q��d��5��Qlu��xkX�$<��X��s$\Y}�X��$���+}�s|N��.�5���o����(FGG111���	LMMajj
/^�e�q��	@a}�L�B����!��r�D_�#��_�{ꉾ�������ܟ|��(�˱���Z믍�o����π�EƳ�h+}��s0\�s�5vs\ƿ�����}΂�<����m�k�B��ַ������@h��p�=Q�Kލ��nv��+�{���{�࣏>�	��[�V�v\�z=�(c�s�0�t�H}�pzu\����,^{�.��/z�F�u�rn�W��{m�ged�H����Z��8>O}ttSSS�����{/�^x�W O!t$ ��:�$H.e7��	!�x���	N��-+S|dnnnU�h6��D_��}�5x�����:j
$F���t�V��m�7#����g׵�k�:��U��ۧWGǷͮ����1b����?22�}��a||��㱲೟���Y�GF�ב��M���)�^v��ody��^@ؖ��v�u��/~�ㅋ���ݿ��z�j5U�r���a�W	O/��H�K�$��b\�t���
}�f;<�\�A_W������k�N�	��r�]�/);�e�E$Y�2�ԝt����t!d�a�<��0B��~���N!#�???��D�%��%?��Ȭ�-��9>�U�+k�R�z;�A�5��g�������%u6�`�w{�,���eG])	��xxx8e?LNN��`�ڐGF��&��԰�Z���u�T-�H�&��F��u{�o�v�o���l���ꮣ#�@��F�2�o'�ߋ#b
�n2�^���A�k����۽Fy|�nG`߾}qm���8
����7�3g���i�$�l�8�.TfQ��ۮ}CBȝ�C�3���g��k�-�?����k�P�TP.�Q��Q�՜
�|.�_l�Sd�kd{�q}��v}|/�{{^9׎��u�@Z��w�����Br����
���o@l���������_�:��p!+�$��
�6C	IS�6v��_������oh����o
(o^��2�{kk�#�'�h8�T�JTG�}��,�^�/�����mv�^�8�q�D/��-𝻗�Kn��6�s�$h߾}�7���4�\��(�5$�$o�*�̀T��#�By���������������\vBV3���������Ən�E������8��p�������||u��ަ��/�<��*ҁB=�K�}���]~$�ߥ��8��u�p;��]m#�jHK&`a:o?�7�T��&���ᅅ�o}�;�*~�ً#�N���gE�mq�O΢�f�w�����v���u�i�{q���I�d{N�~������Sz����~�G�я},Kt� ]���y�6 (	"���'*@���#���@��/,=�����Rɩ����ѽ���YF�+�퓾�����:�ϰ�/Y1�]u@�����F7���:�֪������Z�?55����3g�t��Ab�}PE(nB5��v��w�X
$o�A��zƑ����3����?'��
h4�#`�����~���Z��/�
t�c�Ɋ����s��n5Y�=֗%qɓzqR\ש�})J�i/_��]��\�|y���E$r�2�7��H��Դ����'����1��H�Q�z�I�'��
}�N���T��O��2���譅�/�n�B6� �}F�>O���o�j+�閝�}�:��"�q�@�&�.�3�
��������r����b?"]+h�28vg�˞p�ԛ^k�d����'�,n��'�X�˿�[gm����@~�Z;]����\���'��tWt�[���o
p}|����n���~[�,��$���v�	\Fgu���GGG�o߾x����4
�B��H�(!�m"|��$hOx���Q�k�"���_@h�>׏}hy�����_�$?>�x0:�[�=l��t�������GG곮A��rd�Ȯ�ʄ��]�X����������|��`�K/��%��%$Q�6\�6��^���8=���͟d|O�	����E$#��͗vt�o��z�Ak�n��k�,\��r4��c��Y�Z�˩!���+����9I�bh[;�����Q���Ŏ��B���g� �%ܣH�
� i�?�B�+����OVp-c�Gfgg�Ks���Mlllt�����A�>���m<�qP������a�k����v�ˀ�����FV��-��9v[/̂m���ˡ�����}�T���g>��Ed�Vt�_~JP݉.eO}��)@�pdŸ��L�;��C�-��# �>tm��	���8��}{�����վ����^��6Kb���$d8���.�~��F$
e|C>�	$ـ"��B��!��F}����!��/Z_�y~~�T�Xĭ[�P�VQ�T:2��{�A�@V�?��׿��k�5��e��.#��LD���%C�s�z��K6�:k;�|%�?==�-�$Z����H��{��~/;@b��R4�$�m�,>����Ķ�����LhG��Y��K��ֽ�[t�Lw�q��k��G���0�Z�^��:�:��q��lDD����?c&�څNMM�M�ދ���-��a}sEX@!/��o'�j��4�����[Ձ>�D}�?���_ظ���Ef���3�}F4�k��v�GE�ߵ��Ƴ�co�	���3ӡ������,:'����~���crro��^�Y[����_�*�M@�"�'!#58w�n��N,,,����u���
G��.B���hm�Z�+������
�,�K/�/r�Fg�,��<�ȋ�u�k趿�Te]���i$�����S��
�^|�ŧ|n�"�di��!�|�1������^���4��=�\XXx�X,B�}�e����n�}_�Ư���h)N7#���G���y�v��c�=+!��*�ю����<m��9@��d�E���/<
7��~�K�_��H��^����%R�
��%�<��c�_���Q�T��������pu88>�v�/ ��6h�-�6�a��5��Vb�Uh��Űܳ
|k��\�^�ݤF���Aډ~�O�~����� ��x�ߌO�>�8��WW���B������0B�_2�:��5�w�����w�]K5�h6����H~���d (��'�>��+���X������Hd�ꤸ���R����M7	����2!�k�n�|hi������R�}���������x28��\��բ��7���p�# E�c
�	$�I�#�O>|�=D���H���2e��#���ֱ������{u\k���;V֣��%�a�r�������IJ��+W�<�y�YBz(��u_�=�$���%��R�'F�l����©b��������᯻�A������[k���z� �_��m1��N{V�ce5z;�>��
WA�p\�~\���׵�w����|%�7==�˗/w��<���_Kz��ߗ������0��1��q&�����?�o^��?�����T��Ru�8���	Y�_$]���w���vG����7z7iN�2}�n�h����_�,�>���n�$�U4t�ҥc��[F�.��d2��
�By9�������w��������_��q��h�u-���Rs~�"��}��}�ɀ|��٦[����� ܎�n���||{Y�e���\Q]�;::�1���ŋY�����~e���vΏ���~_9��PO
�"a]���DED�R)��&	� ���c ]\�
�!t��ś���[-��@��u�݋DȮ��;��r��9
z-W��� ts��p�.ܨ��1�.T�]�|y	]fL �
G��!��)DBy�dh�G�Hw��9k�׉������S2�Z�o
� �pt�Or��[��4r��3��<������q���.;�1�2ѷWT�,
��?����k*P���K����y
^�x�[������k��}��[pFdp��$,#åuh�������i��ѓu����������x�6}����}�"���y7�A�t9��s��ۑu;��x�%�cp����!/^\p�q�@���
h�3�@G�r�`��?���|��G�˧�Z����K��_��Z�N#���Q����j��$D���r���r6��a���G�c�]����w��H���l�!Q��_"�]��������zt�B��:��5��>w�a�[$,��Id���<|���w�]C�TJ}������N�i`�b�k�
̶�#����=N���v����?����]�u
:���۩s���n>�vx�
LLLđ���}7.��R�l�cHO�@�$���!� %�Ւ]�'�������}�{��t�����zݩ�$���a���V>ce<0��R@�r\t��o���u��hz�f��D��Z������]�-5�����_zI��gΜ9
'(����5��O@2�S��H׾;����p�0��CgI_a�J6`�����)��jt6@;@�8��l���)�YF��ֵM��閝��.��I��]ח�_�d��8|������_���hpp������
�#�8��u��;.�@�3q��ۇ�ֿ�@��z�9-�ɏ�������ֿ��e8ߎ �Id[Gޭ��u.�vy���kt]�K^���n���/��c���-�3�K���h�]�t�y��E�u�>�ͫ!	�� ���2�w� x�,(E��L_����w�3kɣO=z����UT*�x��0b?�F�FP�j�6���VN�'�j��]����@:2/��R���6D��.���2�ٕ�92@oR'{n����
��Mo���լ�S���#%A���&�{W$?���Rܸ�X,:3����>}��"Ӯ�����3�]���.ù�u�z���k���l�K.�r�zm���~z�o�����:�&��rak�2�Z]䫻�ܑ߻w�8#mU�@C�A���^��ÇOI� �v�N�EH��[��K��Jk�4���>��J��?HΩ6[�M&d���t[Ǘ�9�	pe|�̋]�
�߿cccq&`jj��x�E���$�ܱH����K�����;we~~�9]���g�|���XD�<���c����l������}�ɞH;�E��Z����rR\���\�Ŷ���&�&��o���˗C�ZM�6��@p�F:�w�w���pu!��u!�c��������o�ڀ^��1:8��fdg9Y��M���v>+s�_ߺR���U'�u�D*�N��*�k�����ttBj��ۗ�BP(𶷼�}�������.A%$�B��pQ��;�C����"�ђ[��O#c���G9��o~��.|��4�]�-<۳t�(��p��y��o�k���r�p�y|k�Nv��	��u�O�::�oH����pG�mzz.\x]�5�/��I��-w��>�t�ba�B>��܀n}�౹���(IR��F�f3�薡oTdIx��±�g@�l-��E��#�����}���u|�n�de|���I��!M���4�\��(�s���8ҕ@څJm?�!{
��?���T���t��g�'%�_.�Q�հ�����crE�n�����f����>��eX����}�"��<z8���ӷ>�6}��un9o}�n���w�tw)򝘘����8���K�.���ܬֿ�&�~������DO���?+}�K�R\�$\�v�VK�
������9ϊ�k|ك��c��pIo�q-�i��v��6���פ[���ϪXCgm�t'���h�.]��%	ZFgm@a�R"aq0!dO��G� Ni�)��D�}�'>x�ؙ/�+Z��S�G\׃l^�w�����d9z��'�i{��=�9�Zր��w>G��XX��^C/����w��k�d��y�ܹ�<7O#����շ�|�[�(�L����{���ÇW���oŎ�D0D��ۅZ@c��,��>.��>�e8��+�n
k��|�u������Y�b���F��?t��>�o͍���Z���]�|y�F�WԒ F.!{c������t��&�}tvv��t����2o�J~��4_W��.�|��]ή�^�a�2��d8v�<��{�c���%�n��ge \ƿ��Iw��OOO�moy��'>�K����K�m=o����x�2���i�>/�ġC�N޼y7n܈5�ҵ@�������NJ��m�qI��������3�8�&O��qɌ\���$���k�)����2�@<��׵@G2
�B��Ǒ� L�"!��g�M�亮3���Q@-�P��vk,/�nǴ�ǖ"��bv�(` �R��f,;ԶlI�lQ	�
 �@`X��q��M�E�=�Զ,�j�$R(UYYKV֖w~�w�;��97$@�w"�2���m�~�;瞻�E!��>;���ϗ�8x�c�?~���]LMM�3��'}���
B�U��,�
k�^$��m4壑�O#.�K�MQit
B��D.��nP?H�'��{a�a��u�]�|��0„�!��ȍ6i�o1_6�B����S�2n
�;ٹ��?|���~�z:��eoE���4=�[$S����='�g���Y祹��0���H���Qc�e?x9�^>t��A.A���4�޼φ�)ע�-�E��B
��X?lj2�v�a`7<888ƣ���|_���o����vSi���W����o�c���Y�.�x�U�<���^��Rdd����lGG:;;��ߏ��~l޼/���#��@YhOr��
��N�+I��< �Є(�_$�70!��~�ր�|����ԴI�@p/3e6�i�A���7�!�g�-���J�#�4+���:�m�5�T`����#�/M�<��1�h/^l.�.��>��R�me^��t��]~h�E�1Y�����R	SSS�ƚڎ��V�9�GY�m-օq��j�|��K�+�B̾�G^�tg�����rT�j��k�lf��)D����ƍ�i�&����-��ɇ�E3z�y�))�&D0|q�I�oa�>�����^;^5� IDAT}�U�J%�J�t����\�El������i�kO��J�Q�m&���O��F鲿҂b�P������%��3�…�������8~��ð�@�r��
���@!��I XE�#k8)�������gƯ]K��RI����2�sh�[�w%��%�_f�I��0�Eͽ�X��!���+"\��-?�����˲<��9�:5C�ۏ�ܺ9����w������k�r�ud.����?-��is�
H�ܠ���ة^��fw%����x�{�����ׯ_���Dj�t��-Ω.6H�����V��S�-�Z,��7y\Z�X����\����h���K�:�lm��؄…Rx3�6 ���^d����ƅR�mcm����>�~(CCC�J�Rޓ���;�>l��ź���Jk�k��Y�e�.�#�-7&��5�}��}Q[���n�ymeY^�RP~�,��{���{���D��3x��8�8?��K,��/\}nP$f*��DQ�\�C�&2?���M��dmmm);�7�p�!F`��b��PY�,H�j�'���.}�b�;V;��d+"�f�7�ӷ�2h$Z����碹BQ�~p'��Y���PuR3������������ȑ��<zt/�8ǧ�����?c| \Ps�a!�rӤ��x���+>�����c���(��jxO��x�/�f�`[����E�֠��Ay9��iV�����]�'yj�o.���ŷF&Zג��]��r��;JQ��C�>�,�?����HŜw�R(�A��%#i�4~����d�rBqo��c�v?�|�(��DL�J`k�'5zi]XAf���ږ­Z?x:h��=̲�p
M�oY(�P^�di���sxa�[��ī�"������#���<����w��ݧ_x�������d�&��? ҳ�g�)���%�8�?����:��ܹ�h�T+�J������Lޓ��SXl�#�C"�q�nC�s��r��;�X��2�m��/���H<`x����R����OM9	�G)<i.]D�(�᱗Q���)��!�5���䓽(>�\���v��ų���>��H�M����om��i�^�R,W�F
�%'
�?nR
�f������믤A���(]�EQj�^^^�֭[�����ҥKV��3Ȭ�րvd;��o
(�B
)�5I 
Y")���wT�k��/�cg�����a����Q�T�5p��?DVS�����b�W�G���r]�fvJ����s	��Sy��-6��@�Z�!E�g֤��KE��_#Ѱ<�Os���_X�o�
���D,=����eL%@��H�@���7�ކ�G`����x������ߍ܀�����p��-Fn�5�$i.X!�3o���9���Bu���[�naaKKK�V��	������W��U�%�&�ad��Vd����.�r�E�@YH!�4+�Z7���׿�}�����=���Y��3;;���9,,,���<��aF��&� �FD*��V�e�cܷ^�vKAД�ȣ�7�-��I����J��B�MZY�u@1�
�"2�V�g7G
���4U`�铛
�N5�jY�^X���-v��Y��\q�J��7������lRR�u-,����ϕˍj��<��Z�6`~~>�)$�������^\�x�Z <`��L��x��*2�T�6��B
i(
�w�hw���߾}�������sff�j5u�!�O.?�9�������=����yB�Q}��΅��� �H-m��_J3�7!��j�_kG+�Y ���W@n@8���~!7I
�&s"�n�����[�
��-��ppԿв~�c���l#�f��
�?�Bd� i}mv
�<�q�|#���ap���\:��_�ݻGN�;gYNxٺ�6佱�����R�*Ǝ�m�sM��!�����i����{�Xǁ�^욛���������N �d���[s)Z ���$�O�A��s��)�TfBV���kd$��0$�rw�R��Rs�M�BXe���5�%�`���)��S�@�~�5�&�'Ӵ�[���K[�`�Ti�0����Z�K�$M������M��(J'D��������too�.�6�ۃlc�x��…����RH*�Ҋ�����O�>=��(��;v������)���򓴟�>�H�C���\4‹[4���k�?�]9���ui
�uKQY��<�h�a)2T'�?�<�����.r�Pn���,�[�.5{YVc�e^90Hs�44`l����k>pK?��`Hz3��l�_*A@�5䃪T��s8���F��Z��Q��"����G�<q"�@��I�^��J�6��B
IE�����
�����6P�އv�8=>>�����̤�ܬ���n��� ��Q��Y�q�K�=E�_ci����\#�f�\!`�)@�m>��t����e�"d��K����_�����n�
�*����z�5f��\`KǬ�	S>k}���A�2�v�Khp�ti���e�m�����R5�ߟ�'y��(�I�G	ZZZ��X^ƶm�N\�|y���)S��ax%`M�Mk���*�X��!�E���Û[����=��ڨ���;F���������()��W��zp
��%���l�!����y���7نd�5≄,�ڼ.�(>gqҎ�U5��,]Zi�9�:�PV��@6
�z8N��9���0�4p������
 [,�M�!EC�K*��|�9C!�/����u}�4�?�U��_d�Z G!�h߀j���[���/��?�O?������„�'��!���9��7�(�?2~�kE"�Pތb����O2�b��5��wp��SW�\��)}�9��VV��e�����9���KP��9S߀̽Ecǵ�K֯խY9x_d?dB"�,*�5g˹S�i�Ƣ��/�p��.X��tLk���V��k�7!_��G+ˣ1�yI -Ө�1����	T��h��������,����.�nĵ�5���M���}�[y�������H9�|�ed;W��Y�(Aź�;P���N���`KI���86��̝!��?B�w����E>���Qݡ�����r�T�\F�\F�RQ}�����Q���c��^K��CI�b���#�I���ַ�eA��1��kʎ�Y'?ʷ��Q�՟��'M��S��BXŢW �C���˅�Ĭ4#R���ノf]�y%����L��ئk ���j.LR��,(!im�`*���CSW� e�h���T�U�w�}g���q�…��@?�3���5��
��bM�F��Q�������d��=8�*�%iK�La-�s�?����(?}��x�C�G�T���,fgg�}L4_��@i<�֔i�8�;N�W�w4�Jm[��/�Ss��s��e]�
��5⢁����)�:�k��˽xY��BV�
�*���������O���X�䋩TJo�H,�H���
�o�)�A��ꗖ)��Zk��<˺!�SH��ĬP��,��>E�	%��
��jX\\���"v<�ో�=7��#7�]��
��g�I�V��n5�pݠo
෰o�ieiT�o�hG�H��CѥP<;�J�})d0����}�-�$��m�vnjj
��Ә��N�")�����|�[��ZN� �X�mnh� H�P^�f�R��$�,E���Wr�hF��H�nYX��u^���J��BXebl�Rk~��	��x���ui�+��z�� �)�O���Z~��~b���M��>Z�)(�����o�7?����Z
O��`�7�v斀J��������>\�p���\��(�w���]���V�U"�K@�+��O�ncy���M�h��e���ҹ2 �9堰&�~Q6�jEF���zx�?��ס�۷/�J禦�055���,--aqq����g�<���%������z��ր���4B)Į�rZ�e��S��}G��O�05Z_!�̿���<�x�
�z�PV����a�{
y�_���
B�ʲ$rp�zȺ�r�<��,-	)\�є^�dN�q���*O�D|�\!ҤP��s����0�E�����'�Ƭ�'�]���ٿ�p����摁�bm�m�g;f�	���&~�cTN*��o���B�H%���(�Io�(�|��C��w�!ƿzT1�����1�����I]~S֟Ƣ��.<V���[c��Ca1�@~���)d-���\�k}��Rx�����'�Br���~3\q��S3/�l��=��J�� ϡ�彐�!��
%�|h~��[旚=�/À�^PYVpI�u�~��@�~���[mX����7R@��d�R9�<�n�����9�%[\�հ��R��p�RA�Z�������~<�쳏!�,��X���~,�M�/ s�-��Q�4r �;�{(?��~�k_���w�ͅ�2`�}�qiX���'^(��x�?7rG_Z�>�X�z:^*�Ʀ��033���i3�'�lj�W+��~#��,��s?����x^7wǤr\,��������,��l&�$��hm�J���4%���}�E*gt.���YR(�LB�z�Ӯ��K�F �A-������t�~Y�~�F]�Du�AE�b���"E��2=t
,���K�>��Q5��9 �p����k�,��������>��.���t ���6`裵�5����������瀿�}w��)�(ս���+����>���'�$�%��J@�H�"Q|�IQ�J>k���KJ���g����\�r%��J%
G������0��@Z�I[���q���4Y����U*'�Hv��)���&�&��|N��Zs���4���,<��BX�"���U!�G
`���R��4m
�&;���!5w���,��5 q���Td�����F}�v$s��l�򼨌��?G~�d;2}�J��X�PM��g�	�V�!�㺵�c۶m�._�<��a�h��ɱ��A�֊���' ���5��^����?�^9�&�Y�i�_[��%�p�E��oA��O�=���Q�c;w�|�T*����B�\������Ҁ����K����2Ĥ�\��@�����e���M��
^Gh���W��Eg���j'�C�?��D�6Du��kBօf\e��R(�X8@� Qc4,�LB/�t��4����3�2�eJ��^�ݱo��^��Z�(�[ʇ5�S^:G�zh��>RX��(����s���6 �����}�n�:��ׇK�.@=�< ؏<�<���K����	�0����'�ߝ|�w�ޝ�V��7��[���I�ɧ�l�	���x~^��O��Ia�F��"�X�����?5>>�r�����V�ixO�0r�_�'���:5?��������j�Ж[(�ǖ|��\$p1��yȴf���Ҥ��Z�|���n)�U(��Ӵnk}@#if��Xپ��k
��fY����4p�_d�@c.47+���y����16�mk}���J���^L͕SE�\����S�@�Z���G���/�n�-|
7�~��u��ܒ�O72��k������z�6�C�@�YR�3�
����
�G��މ윸��>ҤG�
����۶m���̅�����j�1%�'I#�ok��6?ik������h4�X�E�X~�12ņ�A@Vn:'�5���^��Y���.�J�jה_�(�5Է��BV�
�*��o��@��"Am�Z��0���nm�kĜX��Ii�Y�u��(�uk�����(����X|kmX
��g�,[�G�){�������3����x�e
8��D���A�zR��bm�
J�e��72���׾�W���N��?`q�Νgz��p}j�J��۠)��(BE��q���z{1]���g�ݛ��F܋h�vN-�A��…%�5��E
����|G_�=�{���o��R�gnn�J%�����ǜS�\E:�[��A�@y�F�r�����具+����.�Z#�(R@�>[��A�E#��p_~+��NZ���Q�|������#��
E��9�5�#-�*\�:t���&�o�	���9��,����L���u��+�<��f��|#��5�[)�9�8�O��y�D��4??��v�}��ŽЙ���� �
��u��K��M����r�k�k����g�E�!9`a׮]O��1��J�XXX��m��WZZZ��ֆ�������z׻Nwtt`���X��p�ܹ�I��ĩ��w+�C�\�F�Hő/�f�#�388x�����u����6����(�WD�ņk�\'��J�Ō�:4K�5_�s��s�.O��_������3ղ�e�e��E��!�,QW�/��ʄ���"_H�%��$����0ۡ4���ť��Q����XL����e~Y��>h���m�d��J�Ŝȁ�[�����:@:��700p����Z@����|�;�-�\�_����n@���N�[o=�C4^A����.,,%ම�����4���r���l.�����---hooG[[���199�������BWW�y��'��y9�Qd>�1�����D���

+�)JXX���և��|{`�w��1Z.��P\�����ˏsJW����.�2���*	��g�%.�kaHo�j��T*4�K��\斑;o)!��W���,�)P�͉�Ռ�k!�W
`J���r�Xzˤ�7
�^x�.o/���~i�B,��Z_ef��Vt�z9s��G��G�j��-'I~߬A^Zp�2�Cp�L�?�  %�B�ܻwt���a葂�8��О��\�����W����O��ۑ������@U����y��k�R�F����  �or@'%��%������hmmM���vtvv����oٴ	O��=��X��IxeE�N4���oB��ň���������8=�����e��ϣR���
W[���+t����!�(����UH���Xk4	1�T�β�T04˃l��IB���p���\k��+IJ�,�9S�K�.\��)�U&�����K�b���/6X
�k/��7�|!� ^o���&�)��֞�.�Y8�ׄ+X���CVZeI�m�o�������+1�2S�?�I���Q�(��_0��
؏z��x�Yt�x׃
�����]0�LG���+�[�'�j�������>9�J��J���l�#��A?w���?�����2@����,����u�֧7n؀��>RF��%s����ފd�MJT_��C���䬿��ܱc�H�\>M��R�`nn.U�ˏs[i!��%Z�~�;w��7�˴z����A"]T�yP�M�K�^�K��s�u�RI
-���%if]#�[�V���H�<��i
�3�5%B��
YR(�T$�� Z/��T�d�9��ǵ����B���k�5�����@�U^S�4%�R>�<��3ϯG
����!��-��R�#�s�D2��(A�j5�6�Z���{��_<��#�CL���]�vnCvY��u������1�.1����nH>}�7�����O}��S�
�_�ؗ;��@�-�@GG:::��ݍ��)lݺ��_����ѣ�/����I�p�snE2\~�ňGZ'ҏ��I�>��ç���155��I��|q�s��^c�%0���x�`9�ZL:�k Xs=����w�Ss��5W�f7�"MI�m�9���f������BS����kmF!�K
`��d&��i�����l'�hF+����O�z4�,m
@�J`��kJ�Tt� '�ט	Թp��fmن֞fa��I�2f�Y��q�6��N����Фdց��%|���~���~�����#sC�}Z�}������U��O[�!�v=��3�8�s��cSSS�(<#ߑ��[���O�qac�f����W�k��Mo�����������#�jT����ȥ�ꬶ IDATlii)U$������#}}}8{���QN�K����mz��o�u���yр?���A~G�3Fu���F���i��W����?'��ղ�ِ�?��ɱX#[�qժ���~��]���>9҂ |����-�@���%ϫ�|.�u��Z.]<M�eYy<�R���^)�U,!�#�g�4��o1�-f���_�ea�yC̽�#�~�c����הYW���e%�
��F�f��hM��~ɾ��
b̬�E&F�Z��]�z�3����t����[��ھ���"\�go��Y�M��6|������q�J���%��wt/�<���{ކ���G8 rp���\4׻'>�����S��Y����qn-���l�Z����O~�رC�F.g��ɨb�ѷ�M޴҄�?-����Я-&��u|���ȕ+W�]~,_�������C�g$+/�1W4�,�� ��C�/ۓ��qءޅG�XY�4K���O�y���&ҍFSF4w)����N��O��L�Td��.F>�^#�Q!�C
`����b��欇e^�q ?���5᳗T �xe=o��Z}�%ےu�c�~�-�2���gp�|R�	���8��h�Duѻ^�2�������~��B ��m`5
v������?k���|�b߻���<�m�D�[�%m��c�����\E��W<��| ���oI���~��G��(E���[��������=ǿ�կ�3���@X-B�c�9W{�?+�ן?/�#7�����c�*w����OMM�q�gggs#��|��X{ɜ�>[���"j$/۵�p
pC�inT��o��,���̧�7���e���^k�����y���ڗD^!w�
�*	~%�U��Kpi��S1�NK��r���H����Sk'��w#+��_�ikx�:��7q	O�&�X�b]��ca�������@�.s�}������…�S�=�x���P����h/܍�����i���ك�ׯ�������$���077�8
�;vQx,�P��;�%W?���v�W��Jݦ8Q" �uE.±�ǒ����C�U�V�!�c,//�.A��,,,`۶m�6l؀3gTO�3��@�.���%��e�izV�R��{�O̿���B�R�t~rr333���N}�����>�D�8��,v�Y�Dc���d-��NȽ%�/ͷ^ͅH�v}���Q��š��5�΁�������q^o+��k^���ǀ7\
`��~9��6몱|@���E3�r���6����-��H��j�^7����k�Q�Eyz���-�X��߲.Ҋ!ź�2O�?N�� �,--�~���ܳkױ3��C�'�]�����2�(As��nY��ty3<���FM��B/��?����ݻwqbb�������8�ǏG��K\{�ܻ��Ow���"8$ee J��"o��Ė9o�X�8t��\��J�qn'�ݻw�ܹs���8���1�Rr�[4b���>$F>:�������Ȟ���3��������5���ܔJI�m9V���BS�D��46YVއF��
�'���;I#�$�zq�@���j��z>���_^V�S|��B�ɾ�tY7�?7�e}ӽ�M,\W�m�gK�,4\�ڠوy��
xr�?K�a4x>�?/ͼ�˃��A�Q?�he	wq�����c��A*n@�y�ט3M�gź�t�Z�\� Z������9LOOcrr׮]���8����۹s'�w��r�[����/k�
�*Lݽ��;I�w�~)b���ڵ�W�^ŵk�p��5�J%��̤�>�ϿsǏ�D1G�;�#B�~����z�w�\�(�gUD~JI�(-���{E�?;d=�T*���F�T����1>>�k׮a׮]��r�����S1��)Uo
Qv�%֟�D�6؜|,�xhh��wߙ��q\�rׯ_G�TJ��g�����MՑG@Ɯ��������E ��s���d�57XKB�4��6=lR)�7H�D/g)#�r#=��[*Zyg?=/��4+WNBs�l_
��f
E�Ia�
��m��L��9�5*'��̸�F;�j�5!hL�<.'�P�֤�)O�D�!���'�d�U�[�t䵗��&@)���e%�SpO�[Z LL3��ڀ�����'�p����w���7�~]�<2��M�6���'F��}���P\8v������&&&0==�.��>��9�Q��G��j�̑��!Er)���*�!�,��)�h_&����>���è��dI���o*��B���s���K�$�G�Y���Dt.��@�"_�u�?+k����|���v��z�r9�H���O"�^s�8�r�k^��v3%Yc1����9�b��a�)�f=���$�xY���j$��B��6G�7��#IC
3h�5H{�rm7�At��p����b����/�"?g[�68p�*�4�$�^�-\�b1׼���=���<���������y�֤��3>P��$<O���Ҵ�u�h�J �
�������{��@sss(��(�J�5��/��m۶=
�í�(���ր��ր~x@܅��B�u'3�b1'�������kxxׯ_����111���)��ͥ��%��?)ѯ�R�t���+�e�i	99z�XNy\\\D�Z���,���RK�����٣5�4��T/�g��h����CC+�׆Pd�-������!�}�G?J�+�`�6��g���O�= ���	I�1kl��6S�F>�R�f�׼!wMm���Y�-`�[汈2��t�,EBk�_w>�p��A�����u�D�C	�&%�I��|��{�}��Of��tZZZ�Mvra�`k���7����[D�6�Q=|��&YY^��-Pj�s�@<��ȍI��J`��QZ�q��K�$4h�H4f_�e�d�x��DNr��i����$�^���[������~����f3<�و�kP'�k�s.�����s2���J�Gh�/wِ>��9����߳����̏"YyXZ"� r��������H�jD�w)+�J������~mYK����l�qυs.r��sA.a���.���M���޽ǯ\�R�)�/���w�ϓ��~:��#���HVW�S�P�H��М%���Z9VR9���~��1����s�j��V�v���k�`��yB
�w�|�)!����!q�9�`?�����d��,8@��)\�n�T��C/�O��{H�a��\�鑧�A�B�Rm����}��@h�W�ƺh�pEI������sKM.!C�j���'���o5�èj$��'���o���x��
��j���'������_
�#���P�K��6看�0��WiwdZ���H9088����d��?77���R��0::�$N'��;(U �ϗ8�D�������P��7E�^gڂ\64vQ������(\<x++�
^YYI7���=�yϩ�~���>}��W��-�/�c��ן��x��C���xl�ΝO�J�3<�'���~���Q)��_\��
�G(����=!b�����[�m����˶y�Rk|�4�
�����  `ρ�FP���kjr.�����d�#�.��(AR�=���E?Np��B###GP���f�Fs��),7W����Ǐ�PWW:;;��с����B��(�fC-E�V�z�/%ʣ�y�o|�����C6�Ci�ɖ�h��j�/Җh��Dm��S�B#���5%��	Y[�)�"p/'U�>p�J.�<w���2&&&p��U�ޱcTO����܂6ƒcZ�yGZ������~r���Ś��J����޽'����1��}q����q��~�p��K,qV/b0]VG�Yb�^I�h1�?N�wd��|\y$Y>p��q��k3�.E;�rW ���Za���Շ��݅�{�	6������"W��pWR>�>�5��&|<��^^�Gk}��^���q_�)|��@8�P��"�
�̥�]�$pieye���l�%�A2��'=�$&�4�4�0����������
)�?��W�iM��(�:�Pn�p��=����9���5o	,
j��J�W+��2��F��[c�4�]��"�'ڠhx�_*Sr@�7IN. k�U�[}Ԯ��|����X�_���}&��� ��>��(6���_��k׮�ʕ+ǎ�g�59�2�C~�\ �4V��Α��'�7&�<���_���0�d�����k�}���Y����wdH�D>�NR&"D�C��Ly�� ��]V6](�<D}���ktt4� �G�*�˘����~��޽�)岞F��G�Z�����/&z����}�m޶m۩��;�E�����,..�n?�I�?=�8
�4������J�|��$c$��&�i7��hc<O�B�&�پ6i�I9�Dz����cͣ�}���voH~�֎K�����hooGGG���лnP�,�d��]!7I
���S�dA���|����ۋ��^�[�k֬Aggg���8ƿE~�z��m��~p�&A����9([���&H�Ґ�z,�fM����PI�Q��yJ�t��D�O��o�K��E3�k���Y��F��J~!
�Hր���4���Sn
8`Ty�ﳴ�ik�F������.)y�OMM��~��dq�:#ȎR0�E�$���"��D��A2Dpq�8���~�ÁfjbzY"�����1��
�t��&����Z���i@�u�+��V���$����,��?�ړ��X����۷c�֭c�[��Α�V�ج�$��1��Z��Y�XJ}��	9NK�H
�MB�V4�7MxMA	������{���nF)������.N?�g��V�s�gg'֬Y��kע��===hm��?�lyr�Koݝ��w'H��$IJ��$�%d��r����p���;U�5 �?�vP?�ȗ����ө�~`u"M�o��TNc����e� ��ѲV�:B�����/oM$꒧D������C�&Oj��s�����g|F��N
���&&&0>>�K����(�����"��HA1V�5�.����v�;�Y�����'H @G>ܤ\�<y
q#�b�n��do�qjI�Q�Se �y�v�Gu$��%��S�>Fׂ�w���ŘY"� jI4��+-�����N���g����eٿ_c�O!��#a5=ʦ^R����^B`�����(�C�b_�uw��_:����a�CV^9Vs�B��H��VY6�"k���F�")����}$m��g��ҹX�T�$A�HBʁ�B����������yr����EJWR��>��I~�������Dww7֭[���ܻeFFF>��F� �r�Pn�p`	^���G��鱱��7mڄ�7b�ƍX�~=z{{Se���=U�8����p��|5v���򜝦z�&'�X���˶��-�_�c�8yԾŌ���_�]��j�ƌZ��x(��`o����D+'��u��Ú�I�@������P�Tr�A/��2���SCCC��)X�Q�ƒ����Eo�N��2��
��#�tû�H���W^������s;�:���چS�N!N^�8�!�i}���ib��������,Ĩ������#9#F-���Z��DC��e��>�~-���>�;u�$�[�r�Hhð����?t�1��k�k�]�n�_
��
�6A�v�؁���3W�^MC’��\}�b�?���U������1W#� Ҥȹ����(�H�\�����99ƃ�嵱/�/*'����:�hkԤhd��\g�����y�4My��8�g�o#^f|�է��k׮Eoo/֯_�
6`ӦM�����|8�ω���9~B(���+�b}�H2D�@<���_6�}��}��O��w��R������9���6�3��B�?�b�ǩn�Z��[�Kv�g$d��X��ڠ����E��9����y�rA���i}��!iݐ��>�:�|<��[�V��G�g|(��qY�v-֮]���~��_�e||x~�w`��L(�����
��O
�}BH
�HQ]�N>�?�c���?��O1>>��������<�����j�7��j��b���ۗZ�a��_�������.}��D��x��������-��M��)����?���]}��׃���$��z�Կ��Jj���G�R���R�r��J>�ȵ��k��f��p�z2��ถO�vC�詟<��U�E�X��4�[�IK�֮<���f5!2O����,'E*2��!�������Ogg'zzz�n�:�������ϟ��ux�����	xW�������zs��i��~���'�䳟�}<�����NLOO����J%e~���������U�]Nס�[M9A𓋔4z#��c>N����
-�����gvd_��~J%��z�ɢ�k �]�쪱K㢁^��D�Fpe���"�)1����>���3����b�����=��._���9��'���� j
���
��+��sn�Il�E��2;19�n�n\���́���G��,�`Z)�	=g�@��\0�� #~�"[�KQ�ƌ�


/�˧��2��2*�Jn���9��NH�Y��!wJ9�.�,?&˵I�})�n��1L+#o�Dt-]S��y����7ϧ�Q���sh�b@�Y��-��P{�=�|���ܘ	�www�>��nق3���_����!��~?-!����;R
�M61Є@�k�P�'�
�#;w�<J�b��j"Pc����_d��!o�����x�e5����>��Z[�k��@�h@[�V�!����g�2���������s�k���㨟�����ֆ��n�Y�}}}���C?.]�t�1�2�@Oƒ�2��0�l��trx#��Ӟ|�����I>ܯ���w�|�_��}LNNbbb��T��pꔺi��Ny�H7"��wߍ��~	g�yF�
�(<#8�
2Ep%�"k��-v�y\�v��\�������c�>z���R	�����������j�Ɔ�/P�o<5��b�)��9��7j[k�b�-&}:@�(P��9j��X��Fee:��*dAh�z6�B4R��4����
�ekyL��������ݍ��^�������ϟ��v�o廎�=�q�X|��Pn��(12F�Y�����@5{��{��?�I)��" }A��AԀ3+]u!@)�a	�5`+�I����1�R	)���~Yw�}--�n�r.�<)&�����W��k���[	4w,^��x�'z�05S�M�����aݺui��~6C
���M(�3�3�\A�f1o�"���݅���D����w��W_}SSS���J]�4ןH7�r���#'�E:�KN��Ϗ�����tgy��|ŀ��r��<}�G�gc͚5X�f
6mڄ͛7�o��o�Q�<�^	x��� ��o(�?F���C���+g��޶m�9Z>==����t��F�|	a ^�_�����{jG�:���e5��h�fAvh�GRTBmiL����P>���O���Z[�.ُ��T3��i��G�,�����*�����=%z(����+��O}��"�yB��C�����V���/�pD��k�� ��1C���yl׮]O��w~$�3D�����n�Ʃ�i%���F]��b��� %P���%l��|����7R����E�����}���,�ú>������
B� c���M�O��>��I�2K)�Q�-���� �����M��-��{�q��7��W_}333���N���'N�H-y�"�%�|kp�@�y� ����{ ��&�"��ѿ���9��o��*|��ݓ]#:�lW���G��@�A�n���G���j��8�讻��ƍ���o�S_ �;������l}�Z��
�ן��N�?�/w7&9���?���n���ώ�B IDAT��R����P�9��w���7b�-����(��	�y�U4b��2!����k(�e�C�����Q#MS�+���R���~[ʚVV�љ��w��)\y[[��ڰf�tuu�������W��aE���^b>�/�w�ϛY
��0�)�n"��}��ONOO���R��R��6��;A&}��B��1�a^?��L:h8���H�\`��G�����s �%���hm��!�jJ(�R`�tn=ЬH4�}ȅ�#����vtuu嘢�lތ�.��@���Ō�	�
Q�s������>��?�{��{#?���p�ʕԢG�ݧN�����ρ�$%#�;�.xT��b��Qz�r"������c$�IHjS-
^���%��������Z|�=������2x^x��O"S�n�}V�?-��@��O�=�g,P���������̤.?r8�6�߂�M�,W��,�
�@;�*k���~�U��������b-�V
���"�e�]i���)P��T�a�e�D�G3�;@.�Y������u��h?===�x��~������71�d�[@��߶5^?R,�Bk�@��
�юV�W��<��[/t߸��=��~��?���0==���VT*��\\̶ ���9�_G=+.�>	�d�����ʒ����n
<j���u�`[y�oɞהr�e{��s��@�G��󗓅�ey�M�I��/��О���|_���Ej�Z��P�V�p��j�k��+z�'�~�-1���������%�
v"�`�B~�][S����26?����8D�_�(rp.c��E��&O��[�(c�I9�hK/qo	��>g��	3
�>.�?=Y��XV>KI%�IׁoV�V��
G�u �`�^��-�PX�>d�?������R�4Fk����Q�V1??�Z��;��
��:��š����~�\B�����G�����ۂ�r �8z�bԳ�4��	r|��������R.��*�&yr�Ώ�Y}��"��r����ɒ+���������6|it�H��G���N�7R�o�
��N,!{/ia���_�_�8f�sz�g>��C#������N	����E���%��k�Sd���c�
⌳^yR4�+A��'�I���Ƥ�>�k�<R��� ��n^���u��[Sr������X
��g�������@�]�����,��ڷ��NY���c�i��U�MǴ��
�e�Qխ�H�KH�ONv��yzaaAݽ���I�.�'$zL@?Jx�\���(Q�G�2��/�G.B��@�%U(�A}jypQ�Χ;��DJ����K�1#�SP�B�w�^\\Į]��>>�E�����
?�6���eS/���t�p.Pݞ�>����R)g���5W�[���:�W3� �H���V��W�P��H9�ӤrA�XQ��vim�~[}����kY��~���yZ��Z�,WœRN;�޽F��uH��$B}�����Ѩ��%��.T��EXO���pm�u������i�R~��Yd�[�+�,��9���R(�P�%����/��
���`;�K�i�#�<����㏟��K/���
����Y.i7�2��o$���>�k��1θH�"
(J�[S&�p��}>(��.!���f���]|%(�&O)�%���-��s�}��������䊔
U>�9�s ��s�2ַV�>�+++);N�R�����?���g�
 �u2P8���2���v���O8�����c��"266�V�g����z�	�̙D���S1��gOm�g�G�9�Lj�ɧ�
��G^�Þ={r��-..baaQM}�����6������]~�"c��a/l<<44t�T*�!�����	O,-ց6@W��I�"^�X�I@�|��P���XVH�.K����H�XzI��o>>J+�sG�m�͍8k�i�2c)+\�"����<~�bU�ɷ��k֬Awww���ׇK�.���ђ}���A�|���,��HE		�h�'7���C��C�͈���O}����������,���ى���:�R�n�OΥJu��\$0��4���*���ײo��b�(�>�x�Tަ�'���5
�7�)41Ⱦ�z,+�v����.��,E�S��:Y����D^����<��X� D��.,,�C����#�w��S���o'��Ҏ|��%x%��f(�%&Y�.��S]�*3�߻��gwO;��m���'�(]O�A�FV���%L��������fEz�_K�R1|�)�g�p�r���3�o����q��e5����6��7�h4FW#H��C�O������!�k)��|��t�Mkn�㛦`4R�����qv�+�r��W�0є~��>�|Ԇ<�͚�ݻ���.��p�f͚4��/�{/N��
�{-�B���7�$���$Km]�B�)�7H��Ɇ�?mhC��
�9�If/l��ٿ��

���@�\FKKK�6���"���~����N���~k̳L�oJ����fsi%�2���p�bgx����H�N"�Y�,n%�8n�3�~�4͊�����9�I%�R�)�O:��p�)+++uk�w~۶mO_�|�a�5Rh�كl�=�8 �5�\�n�5�+ZЎzP�H
�t���o�
1b��}����Zr?b ��c5�*I��r��?Ꞔ8N�ٳ�5$ꥺk�瘲S����N�ը�ž��˿���?չ-,,~\�r~�P��!L��5Ȣ�� c��
h��R��C.�<|��0����&	~\�Ip��>9FZL1�K�ŧ&Ҵ�T���-ƚМA��c>ɱ��vM,������?������՘}y������e)cR	ў�W�o��Ҹ�_l���ֆ��.tuuaݺui�澾>�;���=�X��;y?�;�S�
�����5xr"�� �-2��r�s�;�����_���,fff�hA�ə&���	�5p�Y�.�JvF�;��ȶ�o�E�i8�ҵ�����C�I`�'��Zu�4�G�v�b%��h�(��~3��0�+-�Qt�u�֥�]�t)]��0���C�)ۜm�as3�K�!����s<�]���+���W^I��<{�rW^ܤ(�����.K�V,�;5�7��5x?���}�ZR����Kp)z�%ڊ�WkbWCT�����?w51�7;���aDQ���ݴi6n܈{��>[�U�Y8PbW��0|�yx�u�G���tN|�E|b�,�����L�l��,�FRFs��*}k.������㴦TX�=��1�7�s��*p"�j�����94�O�>ĕ0
܇�XX�HS�h���2����hm�~��oME��E�����s�Y�X�G�����E�o��-�䥰��z/���4��W�!�uZt�3_9`���~�y2۵��`~~Qaii	r��?F:�:�k��ܴ�c�kI#P��M`y��:�P)c���јY��^�Վk��d>5y��b#�G���%@�<r����r6�Ȅ�:�����w����|ʎRHDOd�V�<�����n#�6�� �E`;;��|4��
���������E-�sp-�{����x9Y�G�;�D߉Z��␄�t��]D�2kM�`8�ٯN���Y���HNϱ�h��[���tO[|�Q��{.]Ќ��&�D-�:Y��,�:��S�]g
�b��A1|���Y�~��>ڳF��O}�,��Na^i݇��	Ip&Yb��i��5�Ys��&�go����h/�d�5K�,�l˺@
N��k,����O�����Ҕ	Y��Ն%�N��X�Pt�{�l��g������ၿ�IX�

�\Hciv�.�{�5%���e��*�q��0�Up��^x���Ɩ-[�y�f�u�]���GOO�����ى��v�����ˋ�v��/��F	�C��m���r&Y>��Rb�5�-W@d�&�~�}ٶƎ�k(mථ�R�:�k�]g�I�Z�D���mK�a����>W���X.
������,��2&&&p��U�ޱc�#Kh2��o�ߜk#��{��>��*�
 v�E����@��׾&��WK����i��(�	$�q#b��}쿢��}t)��w����k�����y���+�3=��yD���G���
�����Q�)�<�wQ�S�:A%'�<
�
�\���Jp�_Љ_|y% ������gz���ډ�߅����X����۱u�ֳW�^���d�ؗv����8�pB]���T��X3�S���R��pA�%��r �Nq�������5=�]#y�6���S�,�O��ES�B��>o[*:�:9�H�-٧�����������cӦMزe��`�����k�x|rَ��|�5CJ!�I
�m��d�p
�D��T��1���PC��=�������3?��O��ֆ��9�qL��uт�[��?'�9C
��5X��47��v��!-2�E2��}��r�
�!�"M��B����s�M����~k�BS�,�̚Ā�k �b�4���;��(��s8�0´0��@kȯz���FƞyƲ���A��>�@�E�'�]@��
�m�;�)��L@PF��hk��?#Ϫ��;����?
Q�?��/�E��9�\5��(�j ��7��A����bg*�i���kK���������"���aqy)��---a�����o�;��(2 ���Ĉ����C.���|�C������ӥR	�r9ޓ�U��W�]��Ե:�V���-��ưKv��h�5��hm�E�=���/�H���-�2|'ܐ���9�vC�	?N�p�.R��Fkd����]��QK��-�A�1���o{{{ֳ������Ͽ������X�ۿ
Ǡw����e�J��>�q������Ѫ���0�8gN��ڹs����nLOOc͚5i8:+Zз�æ
����Wr�i����@2/��Z���t�2j�DP>�j�`1�����+�o*�.�/!iQ��A?pȲ�s�Ie�uA*8�*�1
�cJ�9'7)�^XX�������.\8���Y�.���(A�"n-"�?]kb�b�I��Q�r�%#�����w=�+ɉS8�Q�“�Ӥ4�kP��}ځ�JG9<O�>�]���7��'��Eྖ��ҝ�c�C���CV'm�?r4����:1�^�$�Z�:��I���p�ϙ�Vd��������رc�\.�&���S�򓴏�L]�E�!���͸pp!p��lryg��\��� K��GʍX��-9v�s��	�yym���SfUS�$�\�#�/���̽����B(�z��)�?���/�A��?�,�'}S�rc&�:���2)�U$�@�-��̯n�����@�x�����>8J�}������3�]��xR��"*�X��y��r��H���ni����KB*|�G�/�b�)8�Tw(��Ҳ!'��������7d�t^G������
H'�9<�@!Y���Q�VS� �<���S'NX���OZ�Z�'->�Gh~m�����q
{��'`��3�SQ�����^_�;&(O?�\��R�l�/�Yو�C�|E.bm��"΁�̭�+.�wv*QjXH�I0{��� ������?�G�E��	�_N�����gu�ھ���ի�����LJ�P#��E&
�����	')���J���1Tc�%xՈ
X���yx^y���~�s��q�cfh���L����
�󼾐�"�'eJ��	�IY�.��d!م������ <�O�c�PV����lg<k'a��N|�[�h�4�{�αW��133���Y3Z���8�6L�y%��Av�
����3�|�|�i��y��
����!i� !f_�4�kb��F _��H끼/�Di�j�o� JE��6{�E�"�EQ��.--����m۶�/_��nYd��0��&��	�
�\.A����:�?���KA-�N)��٣���x�@
����M�����x�8�,�e��9҃��������Ҁ_l^E�З�����Qd��k/���7�CR�رc�(��޳Z�b~~>gA��y`N��r[�H�|��5 n 5Q��IB��mĮ[�$g��>Z Z�E�a���D���h}�:CV(�V����WS�,�|����GFW���N���ڿ�����(�����Ad�}�� sS�;����BX����&�C滱s�>{x׮]Ǻ����ёF�T*�{M�4��=��V*���r���\N>�G���	�A��o�!�%��D:砗���Zu4�S��Z[Z�&7�����*Gi��Qc�,%�3�'<¬2J���<Q�V�u����뿎O>��x�����=����͕��TZLQ7�Ґ^J�N7��
1�@�9u�*�O�h���}��[��.���4�Ʃ_�(-��G�R���"�,��+������s�ʕ+u�=�����mD�y��b��k���%�����iTJp����6O�W�4+DHk�:���v�WE��-4�|d߭���z^`���ѵ��9�^��Wkk+ZZZ��с�����OO^x�]�ء�_J>��O.�<���EX�;@
�����<ZPd��1�5�A�IN�u���������K�����/���Jw���<zI�V��3�V�P�4�]�Z�+���˴F:T�ey�����!�8ipI�<'~>�n��2�[uh"�=)
Z��
$'�f,�}=
��6܍�M�@~m}���ⷿ�������R����W:�'�6�oQ�ha!|�o��t������C�h�?}o�X;�C�/��qLq��8�\��8�P\�>����L�~��9˗�9�����m�	�j�1�#���H?��O��nj6


/�˧��2��2*�����]���Iˣ�5pj̺i�������y?c�!.������Ǖ!M���iĞ���ba1�`y�>��<rG`Y���?A������À�k)�������h�������ގ���t'ߞ�������{���d?2�O�?#YD�����AR(w�(�km�T�~ҫ3�m��w�ӿ��������L̈́d:L�N�.j��(�7��;�z4���˥0���i�o���X�1�N)�O�+��|r���_����˄&ͅ@���:X
�tЄhEA����������������\P�Vq�}�����DžC7m����;���l��3K�ܘ�Ot���.ΠqEi��oG�|�PtD,�>ϟ��G�=XG�̔��=�U�C���(y��=����)��7��aq��'�7��Q~�����O�5WIx�C�G�TJ�ڇB��?��j�WZ��t5噿c���B'�;��J� ��OS8��B�X�'�/�9L�;N7ڊT��
X[;[�+JK���|#ˎ�d�#���@��C{�E��t�x��ٽ𜊵��c�\}���r'�b3�;X
�����l�=����_�a�}�+_9�cǎѮ�.��̠��sss�T*)�E�����ށ���OX�hV���X��H�z�f�
iY�A�K��e?8+��]�|Py�N�h)T�k�<��p�I�XHK���H�O��
�֩����G���VrJ_P���u-�}��c_��W����&�h$�![{#?��/C��$�3}�sx���5��O/��ȳ�I="���\t������#���kO�d�(��C�A�߹��VSm>S\(bP�,`N��)\SpiW���~
�߿}/w��}���w�,�Z�-��E�?��I�{۶m禦�0==����:�(w�9G���
�A���Y���N�5"D��E����b�^�Y��9~pm\Z)1��g����R	�<!+�56������y����������+��}����v��������g"�vYt
�Ik��"�P��ߩR(w�0d>�r࿈̍a���?jтF/^��>p������� IDAT~��t��J��/2��ށ<���f% �;a� ?�R=����7o�;�	�@����5��hJ�#c���a4�9�%�Ũg٤�#MI��_�ܴ��9�{���Jp"����y�^Y�0�.�}VVVR���[�R����X__.\�p:��,��G���������ɚFR�-%��&9�.4������Eυ�t��J��P�Q
JraC#.�l|�c���"_O��B�YR&���	�{�=S"(|�K-Q����(J�t(ϖ|�lgR�uC�a�Iؒ�ֆ�_�7��.��o�~�T*�������T�򳴴����:_������U�5�??&-!eB{���!/�����Y��i�����Q�l�[ [JM|�򚥅r�|�D�B�է�����O�t�|���r�}h'߾�>\�t�"�i뢀�݇��k�|��&�B���)t�3b�"��U�t�K���n۶�5k֤Q/x� �	�E���?�͚�[�r���)O�@TS8���`M����ƚ�	@��>h�e���k�9��Yx��ۓњ$�/���km[��<O�ҵ�}��O�G�����rJV����7����D�}��Vխ�� UɖB�����I4!�,ٍ'ɲ�ɒ<�m�4$$�&a�
��-[�d�<,l���8NxM^�_��c�J������k�u�]��[R�}�~W��9{:���������T�m�]v��{7C_p���?��k�3=�H+@=-�#�<ۑѡ$"�%��Oϴ	��z��c��.�Ǭ<����y#�ܕRm��ĬN���,��1]
�E���%��������Z�4�'�?�o:��s�!_���-�|�k-�`��Dx1�!��y�cU�H
�Sy�͵�6��x,�i�5�$�6ֆ ��!���2&�c�=t
!#�Vn���!m.������/��477���	���>�Ϫ���׷	���m���wS�q�O�|�r��j�m.�b���1��$ן	Xm~v{�~ح�����P���{�С�V�Š+��ى��V455��A���q�I��[2"���"p	F����Tgfd;9S�5�Iٮ,���5��_'��fј(y\R��(�t�������صvH��K��ʉ�1����133���I���bhh������yg�y枍7�5J3�Â�,�lD��,oR���?<y�(����AVzWf��T�S>����~��Y�
�n�]w8AE�����7I��P�0���x'��)I��]���U7nęg�yϱc�p��q`dd����������8��?\9���2����24��,�cHhA�R�6�٧�5����79V��֏Z[x^ mU�ui����
Bu�ʨE!�N�T�'4���������J%tww����V�½}}W#���Xl��0�(�����l�);̑+��[^B"� f���e�hA�g�q��x;p��;`�
������n
n�Ϻr	i�ڠZ-��:�yn�,sh��,��:���S^b�5��q9�k~�Q �LW/�h��O~�A�y;�����'(m7_�2��>A3�S���)x��,f�+"�Dq��HY�|�F�����+o��۴p���dg�i�D�,�_�3.v�H���ݍ�hhh�J3soI��1�I�c���#�ϴ��C�11��~��lء$�(W6�9�Dĩ��\�(#��#���zx�B��	��tuv�//�o}�FTn4D�!��SD���E9ٱ��K����b�)�'���.?�!�9x�.6X�H?D�P��w"��KEDZ��)��E��Y5C*8ҽ�p�b�y[d� ��#e)H2���,:҂��[������;���������҂��Ntvv�^�z|x�z��� �	]��H3�cH\�g��<��KXr�%&5F��6�w�{�{O_ߖ��:�n
�833��-hm�H�ʙZ	��b�5��k��]��O����
�O�є�j.����)�5��L	�%��mB��G���*�ա��t\��u��F�/)�|m������y\p��x��� �&�b<��4�N�sH���
 �tcbv�B�+Qye$�A7�F�l��VIskL�
|8$����!�^�M�
b�.:w/"%#i��$�À�%�J1S%\k�s"eH�.����	��<0q���~���wޗ188����7B���P	�5�^ZǸ��Qx�g�m^$�Ie�3��n��I��uJ\Ք�Ҫ����.��l�4I�^އ��5%I�^/0�\���W*��Z��F�X�p�|������ݍ#G�l�}\Cr5�]|��	�A�}�<,�:s������W\��A�<����a�`M��`��(���{���w��R,�܀R�x�`�̾�4\�Bb���e4p* �L��C��y�H�̻6�R~���D[+&�6�j���qѮ��KEQ>U����6�\����066���acÆ
���h�݂Hp�@e��`����(����?���@�?n�G�x����{�/�5i����
��$��+'�#�[�k�>�c5��c����~-`�п��i\�O}�ӮY�?3�-?p��f�3ɕ�$w�
��?����\x�_E�����Q~��p������o	�%+�E�h���t�Z=\4��j�*�G��m��l�>�WF��ۚrυ��>v��qM��'����҇_+�+A|)9������0��W�P@�X�J��G6���;���bb�e�����%���%-�,d�#Y��	��ضbKFF�~�.�:�"Yc
|�ID.��Q�ʁS�P��K����[$8�O+C2`!윜��䥁c��,=�9�>���*�ȕ��^|�� PY��T�3v���c�W�wbdl�+|����_D�y����0�����;�1�T��a��������w�\\\�1����&2II��o�h�8��-��s�K[��]�}�,��g��a�#D&���F8��:R��g50(GH)�X��5��������' ��\��~�"��"��W��q������0::���1*��
�?�3Az��%3Q�d��ɲK�Le��$s��Dk�e���U�i����l�6�q�c�f����/�th��x��}�m��;P��,[J����/���X��֧�v�G:�t�rW��������;�e�\��0�h���R\ՄDc��q�#��j�^��x�	*�-Zzɒqf(��Xz^�6���;j��"i�K�`Y���"��yRc�4f*4;He��ɾ
!�t�.�,d�P���::��8����9���`zz��������EQ���b��7��Zjm)��)�.�',6�u7Y������ZG&e9 �o���)f>����1���=8N�p�k
p�]>c�(�lR�V����[�
cJ6 r��@�4466���
�WLL�����:w�hwg/���
CC>�-����l�/	
�j��S|f1�`i�g���,F9�&Yn�w_�vIq�p��Z#0��"�x9N�����S��r��%D��9J#p�o�b��F455i��s����������#���\^��+/#�-h�@A
�(���b
RI��Uc�Sm�r-!o���4r�͚$5MZ�|t.�eZ~.��h�#|���u�	��"�Ĉ��"'o������i-	����T�}:%�|��;S��y��TSh��T�T(���Ͽ�|84m�&W �����
�!��@?Bd7���@�(0��Q:
���+\9��($�D�����?�o bJ�����/.
�#�ɢ��=&��[#D`��oy�v��?�y��Sp�S46�Y���QV�Us�� >k��,��c)�5A�-*��Q*J��y	�e=�!�km�>`�X�u
܍��t��j�l�6I%#B�FH+i�~)��Cs�Sdib��9~yt�\�+/g��hQ�$�U�6KIe�D�^ ��7
�rЬUA�Xa�q6����π��ȉ���݋h��2[keH�*����@Hh��B}��%n��ק)8��!'v�]���1�!�,�������s;k)��5*=n��
H<�����T�\=p��榦&�
8���K���:Y�w���\�i����}*�l
�eP��?G
�~�����J`|���ĂX���)"����r%ק����F�߿��G$��@*�$݇�m۶;�~K_�8�qS��d����_[�
�M����|�R���vPIvd��4~�1L�Zx�T���X��۵m.r��c<o�$`���+,��e�ڤ)r,�JVy�7�h�w��E(���d"��_��+/C!-�Y8�Ikh@�DdO̐R���|�4p��1��ȉ4Đs���S�r��@cV�򘜴%�1�\����\@�d�%�?�Y0d?�v�e��K������p-u�\�${Ư�~�Dր��l۶M�%���]�f`C�qilll����y0��Zgyv��i��oD�#qݡ�(��z����?rmB��{���w�H($^�pe�q�71��m�2*��))͝�o9��R�Ml.@Q�H %�;Ogŕ�q��,�|8z����0�7~e�H40.��$k��ek��_{?�xR�)/�	�C�8��RB�A�ƤP�ւ��b�"��r�l�hP�������hb�khn./A�������f�2�	�k@��b��������A�3C���^JO�n��r��I%A��tNNL0��Yx��"33�b�5�,��P�|r���z�	��/�9��b3yh�
��
�E�P	�}H[h!=�]ox�k�Y��/��;���edv�z�[b��y���w%����I�'�.�>�g��.�'e�c�&G@֌�/ڐrc ���܌��W�!Y�_)R��
�n9���M��4 W�C�-U�Ͼ6N��ȏ�Y~���Xu���ڡ�|�%���ep�L#{4Ѭ~��8o�$zB�x���9N�o	ʵ�)4.�4�9��
6ZY@��?�$|�L�����e.���T�Φ�6����A3�yZ =��!�Y��I-��V����䤵-<C���&א2���L��Enf$�C��|�5v�\�V���.��עM�l�\�*�"�I��-��55n@�����MMMhjj�pZ,�^�ώߩ�F��T�LԐ�3�0�g�I�)�I)�k�f���ſ�����M7]���+�@�iA��^WW�^K]�@�Y�J9����
מ{�
|�2(��R	�ʯ�>�����e}�u���O��������eۤH�A�{9­���}��jD��g�ãqi�}��]~rq�+�h�]��@�9p��O��:{�
�R4��������g������.�@
��3�NI@�~%���
�
1sR���^J���b3e�1�x�K�fk�D��v�t���n�E455yw �vA����
�},U���C�F�#�E��俤�P�K*3�5G��w^���P(���	�b�l8C�*w(���I	oh�?z�5������~N_�4��`�M.�����K	^��t�:�R�e͐�^{����5�c�9������s���d@||�RP����' 9�ϥBr ���8�	��k�Lh��|C�#�`$��r���j哄L����ɶ�	���;D�夨M������CR�o����Pc�B&p�m�ў����#�E��u')�rFk�Q�v��}}}ZT+@9�����:����v���/��1�@��.[�Mi���~����呇�(SyQ��O&Jʋ" ��y˶�:_���9�[��?��}߹Pń�}}}��%��[V��,Ÿ+����o!��+�R	�ȣ�/2M��A��f�RW+C*A�W�C�d�=�
�XH�+�&ގ	�������Y��SSJ�7���w$A��Hïa���se ���2K�o#8��H�Z�T��M�<M�U�e�rB�_��Ic��5�D��2jy�5�r��I��ߋ��j���@�4f]�6�jyB�AE���VNR�s���T=@KwW���@�_l��mà��] �q�zY�j������9������\1��oÁ��M���r�� �lmu��˫C�r��Y�`P��N�#�(GQ��Qy��b����vtvt@��o�Pq�~���!HźY�:�S�bvI	(�sZC��9���"�/�Gm�= �i�|��ka��޹,��%�����"��?k����hq�|NBM���r�e$WryQDc��-@ ������8�i̱��,��AY�(j� ����)˴��s�� ������[Z�yj����E�\�ḩ�4�I�z4Ag��"Z1�
�ִ2���a]W�|��������b�/�!Aׯ���11|�cA�1���$�}z{Щ�����hw^Z�cR��T�p�%x���dc"��Qٱ��~��`��
�^8kmbT,��ֆz�2T.�݁ĪB�_(�r�L��Rf���}�����+K'Eh�~�=]r�H�Y���	i:�Y��A:~>'dN�`�zש�Z�m��B��_�q��!+���hZ��QI�;�f�J�(t��r��+�,�TcU�<�%�&�s	M��Bs���̮!�I�!��@�K2hє$�#
ҥ%$$t��_�^�>��zIxH
�~jʄ���d(�I%.d,4�A___�ݻwK�}�r�̐�'-2�t�敯DGG�����܌B��݁ffgp��8��
�`���>"��L����y�r�e���[����c0��� Ե�E���Td���C瞳3�3)����f���������W@��_�GI��/#� %�ss��B��mfH��.��[Z('�1����r���=o?�������q�W;�	.լ���sY�!W(�N�hdL�\Yw��ڮ�m���k�%��\�e�E�ĸ���d����R4�[2&r�
Յ�7�
rR	M\�	����|�M�!&��<��qEM��HE�(�}���ɺe�Z$+�"Y����g�"*�-B���C}}=���J+��TBs2��`��"͍�v����ى���
 	���A�(��8��Q�3��������B
1��܎��8���(h�(@�o[b��EIXX��R��]�w_	�����������B}���9�h�����~�����=�����w_��w8��k�|�)�<���vi����wJ�O��#��YI$���������9�h}�5n�Dާ����2�z8N�h�Μ���Ő\�eY�3�+#=�eM@�4&�O�D��<I���E�}����d	)E��K�4E�+T�
�g�����l�:�¡s��o�3�N�	Y�v?C
�F�s柇�liiAss3P��>�->巁�@��>���p�������(�Jhmm����m�s�������[�;h`Yz��]���7���)�;��GL�-����x���7&9�Ӓ������s֥�}655������wv���n�����ß��,��B}K����f�(�P,Q,����]�x4��%�'�\�������lSD�����[��s����:h�/[d���%ɗ	�-)ڵ��|��\)y��n:�ա��6�r�g ��#�dYQ�ߚB�K.�%�s�˲
�s��̎�P�sVc��T�Ke�������]�ܬ�x=�rB��6I�2C�gnɑ��.�Di�c0e=ST�ƲQ�
�y��+n�E1y&}� ��,�Ի�M��{�����_��J%����6#V��u�*;�}N�
�31;�#���H�:�P��iI��`�T��Y�vm*�?�����׼w�}��d�؍4��O�v|H ��Rܸ4v����-�1(���H��@�Y흕eK�/˒�k=���-	���ŧ^��Dd����?�[PڒE���>vie�� ���uq��	Y�v�HjM� IDAT�O�--�!b%Ka�%��\�e�%����XL�d����L����2=keh��,A�?i���`Cc誕9Ii�������,0�ԩY�[e�K�1�� ���/�J���@GG��3��Zi�$�Py5u�@�	@��.�)(�Ҫ����v�J%���{+1�H׮][�3Ӽc�'����d�	M5\�n�¥�mmmhooǗv����Js���];�N+�w	@+l�7 �p�mC�/�y�]���DWWW��"-@�~�x�g_���A>�!%��^�dש<���\0#�7	�e��ژ�NZd�����	�Z���o�O������e�Q�8�%���?�Sr �U�m�E�-����T����c|���������TS>�]�
��K�,!�ˏIE$�N����֮S	d٤.e�XW� ��Xa������ڊR��R���^�Qĥ��<���D���
V�p����#�dסC�.�aAi=w�Y�v-9�p�i3;����܃�v��&)Ϥʆ�G���Gb�"bR\�~'�СC������@7��@�K��#3�/J���Y��z��3��l��|.��b��Q+�3�!���ה��H�B+��I���+{��?;u"�$���(�Vn��m]���ɶ�6�Ư��U�B��{"�|.��"�^M��rR�ej����a��jL�&r��p|��������.~N�4���{9�j��_�
A�x�#M�<�f��E;����(��'A���&y����P@[[Z[[��Յ��n��_��Vw)E��������`�Q���F���M�d㙙444`qq���(��cp�ڳ_{�k��ߊ��'N�����YZB46�)�7���l���>�PN{����\��2���5g'�����z�rU(P(�ޥ��B�[����n��u�FY��ߎ�;w"�c�q��:ߧ���m���XX���8�}�!\��o�gTsk�?���� ����_k�#�>��(ɲ�����mD:^V�f��`�ry{��H��5hc1���}�.�@x}��vB�!�\�Sr@.�.�QC��礄���"E.��2��^�Z=CDT���OJ!v<�,������!�j#�r�כU6g�BmYY4EP���+$[��
�\Z[[��с��.|��_��oDZ�C�M�@3����>��ƒ��r�sA�|Y������hA�:`�#y#�&c�w������E!�'*�[ lA�mi�����7��M�UV�Z�a]�
H[�`���ڵ+V�@ww7:::j�酧��H�9d��z�C����9e�#�HC™s����]�,W�h�$	����~�G��PMIZ��U���"d���f)`���[rYvј�2�1鳴P�`�h௚���."M%J���E�N^g�8󮵑+!%C������Y4�I��>�}�����}˲�P���(��Ri�pϩx����kk+���<���#�l�u/�r)�A��
߁H\����]���aXB�����ҭ�޺���|������������m`����5g�`r�I�Q��#�_�\���@����b�H�k֬	\vZ�8F�\�O<�����cǎݽ]]��ė������ψb�qy�%k������	��MZ{��l۶ͷ-��!�����w���R�-+�𴚅L�+�]Y�m��dH��9�1�!�/G�, ]���W�K�'�r��,
\�uʹ���E,�>�ve]��%#�\�Cr �e�Zi�y���b�1�\ J��.�wJm�fg��_
8��|R!�,�-�m��?��,G�h�J|��)HC�M�����&iJ'��򥼿ԅ���U�6�r�+t��0�!c�,�*����
��WQ���۷a~v�s���P�u�Y����LJ�q�ȑ������i����˚5k���	$ϓA�����Ie5����"�c|�{ߣ?������'���N����u��Q466�.���ގ;w�����/H@>�@�m6�87�*u�d�v��
�֭[������rٻbm�c@Xr�mL����:��r��@ �gm��'����Cei�R��gA��rD�@�$�^�&��p�-�{�
2H^C��iD�|i�Д; �����\rY.��\^4ј���KL�$y��P]@�?�]	�9H烻��H�E�dY.B}�uMRI)9Z:*K*!���߯��Oh 	��%'�z%�� P;�im�����0��`��,�?�4�O����ſ-JY�~��ko:v�&''155���,..zגcǎ!�c��o|��ի��㏿�g?��t�T:�PW������	�G}�01Ll��o��T��n-@�1;U��qLV�8Q�]���֜�ٮ8���PW���E��g?��t����џ<EFFF|�r���Ć
����w�[E���=Ͱ��/�!x�qitߗ@���~�G��[��n���q
tJ(Yi��<@���P:� Jv����34FUS��,�n��X T������:5��۠]g�@�������(i�y-�<�K.�%��˲�fvfYs��$`�s$d�r��9���yi�v�����%��,��ʪ��`�{��^J'�V��k�JLڠR
��W[099q2��VX���`�a��r�L���S2����kn���~���LNNbbb���(�˩?Q�\.����r�ʟ�������Ux��Q����a��������@���%����G�a��	r��=�01�:+�k�1Vuv�/��ޕ+���/I�\��W���1;;�
6����w-��)����:"_�{顢�b�52��ݏ<�Ȗ�k��
�-�+�2
��q�[y	�%��e���s��tN���R;�9MI����͒�y�!�T���Oc��yM4�v=�M�[sO⿵� KB֙\r9��\�]4��d��$)Y��s!���2((�����+碙�"�գ��!�>�<�Nc������d���ke���o��
�Vy/�2��P�����0���0�#��#��������[��Ν_������(���055���)"�E>���������=�]O�Y�Pݯ�7�z�08�q�?��o�	����NC�]u-�~�K�������CE����l�)���y������������?~��>�	YE��q�M;�ցy؅��Dyw:t��%`#�}�$���Ǫ�$J%��W����k�
z��ɣ�P9�O�J�\�҂R�d�R1]�,W+'��#�PV��ܚ�K.�%��˲K�tPșc��!��(ܹ�����d•"���� hחUwȽGSpB>�ڤ(�'�<�<R��X͐�''?ɂim�ǀ�����Q����r0���I�EQ]���B��c����0==����
�[�ɓ"@��s����?�Yg&���"��Z���~��OSiW��
���a`hqy��Fy=�����enn�o��bO=�,\�4sO;�#؋tC�p�¸�K��fc�E�k�\
]	��3?�\� �k~���dڐ�!�[�)�
T�Y�I��,�[c��H@_���j�˶�P��� KIЮ�<h�L�sy1$�ryQ$Bh���<gYB���%x�n6�௵�N��B$�"���y)rR��
M�2}�L9��ə+Q�h�-8T��|
��h�������_泷���-��fX��AX�?�t�O�ۨ�q4C��/��`nn��󘟟Ǣc���r�[~\�,�I\.����~��Oq���e��M��v��Cl;�������H����A�p������I�{V�r��C��P��R����6&���K��u�=A%VwR����1H;�cQ3?.�}Y�6nȶ��|��8^�����X|�:��;%��+!�b�5�I�K
'����ʪv,�\NFr �e��K�p�䪕�٫j�Ӆ&8-?t5�9o�m��i�����T�h"�}�Y"�9�Y���	K�Ӑ�B*9�-wz�i�u�>�L�[�������\��|���0������1|ۭ�$%`�(w~nn������;�;���C��CU/��oE������Etwt�Ǿ�W��j�+�������\.��i�?��qW �Â�lQ�~�#�<���>�C��ԡ����4E:^��v^GB챴h�V�!f�S*&�=I^�L�����j}%	����D#Z�b'���#�d�1�$Q;�\rY.ɟ�\�U4� {$��Rc�y���[!�/��$]N8M��HV�O<��W;/ۢh���1Ģ��P��X�RB�\������^��
T�mR�_c�W�r
v}��I0���es��2��D�����
��'�`��}����S�X~^j�u��x�0���1��*;�E��z� �'����3�$l
��� yT%�K���(�ni�����
*�5
|�wO����+	w��!De^ ��gk��eD�����v��-��4�6R��J��m������A����r2�+�,Uj�5�h��4��&?�,�+'�ZL���4`�s
1�rҒ�7���xz�
�K�k�2��y.�M���tJ������	:������է��~xk�oך�d濊"P��X(���/���<6\t"�����q���q��a��/iy��a>|�>l7%6����19=�*��t��xr?ҏH�"`���1�
�]�I�-MMM����I�h���I@'�?9&A�����QY!%]^�!�V��:ʴP�ic�<�1ߡ�p`�)SR���R�H�˭�����x�)
����_��\rY.��\���{&baCRM	�/U�
�|`�,���	6�!������_Y6M�!�@���H�eC˯��T$�6H�/Oj[�.۟���P���-`)2T�3z����Q(�����W�^��|P��?����1�$w��in�?N;
---hnnFcc��������@đ"t���8��>b��ƆB�	�z���Çq��a>|��kD�=
���sGa�IYu��"��"^�z5 Bwv���`J2�1� R��a��E ���[ZZZ��؈��zD�}rg�f���>h��[��βU[�#�/^W��
�$)4�)�h|W����j�j�&���ȏPy���=�"�۴�$D`�ziu�2����i1���<
P.K���	&4p��
�&�fW�c^S��TMB�F��_�9��&?~���,˖��iք�X*x9!�ܬ���WS�$0є8�F���Q�;\__���F����T*�է��{�ot��m=g�1�p��Ed��l�� R*���~v�9�����f
��ϣ��.��)���&/�#G��*����~?�Y���7^��p�
l@�d��/��?�R��n���$����P!Ƙعq���_8ٻ��"�]�<��ֵk��U.��&m�Mk7�	�=.������� =f�����FT��E�ժ)P��5h�{Y���BJȕS�9�e��繫Sȵ��U��!�"E�����2�SV_z��rr�e9%Wr�
���F>����q��W��j�4�īI>k`�K��dٱ��A����ʁ�p��Nm���?u��i���)�
�C��+����r�~s ��?��/�hoo�_�Zܹ�&$؋�6X査�,����1Fza��:��,�����155���I��e��Y=����_��|�Rے����7��]q���O~j�/\
x�7�r�z�o,��N��|���b������
��@���dR��9*��=���Sd��СC�׬Y�gnn�r�����8����j�AH_�;��Pz�5�T��5ŝ���߼�O���'�עH+�f)��s�,-��L�M�4G*�5��/-�Y�	����҅$5��كkdr�e�J���Drd������yJkw;!��BB��f��t�3�Y����� ��g���\��J�?d���DS4���D���4A��"�B�Mn!�7��!-(�E�ɂ�����UH\<HGv����D��<��*�2�}��^�ۛ�C�"�p�=�y|�IMT5�D��~�q��9�Mo-8��W�B܆����W��6|���أ��6�*�]����??�*����(��o߾+��\�P��;Yq�+�l� ��=�>����]](�(
~1�a[P	ʳ�g$��E�����jc`Y��e�ݺ�ء��h�vx��%�D�������
Y�����vZ4_q4-�9N�h���7��?\��}��˪ˁ.A�-�p������P�_]]a�IE/��r*���~�F��"�D]M�B�fZ�~5��%�|rb���8d>��Am�}��
���vSY�e~n]�Dô�`i���@9����w���	��Jҏ��I$��,��p`Ih�	Tn*u˞��7�y�{���133�n(����~W��ud��)�2Cp��2"D.V9*#*G8r�I�������w�u���06>���iLLN�v,&p������hn*���M�F���ᩧ����7jFT���#_we8x�	�#B����x�=��w��bgb�K�|衭�\�q9l8�I�wl.�g�b	 �N�+�@�����~���>�K?�����{K�6���oi����JOi�8��}��<�+��j￴��k.�YnL�9�����	��~��x}��Gm�
O'��K{��B��2���8�+��$Wr�$�lx[Og'�?^	�>��c�H�hH�D%]l�"%M-�,m����V�����B �㢱F��i��ʚ�|Ք�kQ ��W������R���/������]%�_��I��j>��� �8��W��������,�������]F�]dÅ����Q���b�&���ؔab`�D�b�a�]�b�صԳ;��|���O���3&�H��� B�?=7uܛ������:�
�@ۢ��&���7m� �:Z�K
�0�FQ�ʵ�{ɔ�;�Z?	�	Vy��I��|��c��K������2d��]��K�%?���|��j�y����&��G
_4|���z�"BeKD�c��/��.�Z?eYy�"��\��T�(�@
�����sK��dm������ZpS.//�1����O3��(�hnn�!�Ƚ!�"<i�.Pp-f_M4vE����5�+k}�lS�|	��IW��ZkE���7/���,2�6�eY4�Q��_#�[�Ivú�H�򋋋��7���ήHTy�����\�,��!CJ^&����]�z�*�J�TIzWG��k��}L!6`��d�p�O�<U�1������Qo�ڤ�DI:c�Ý����S��ܹ�:���	��m���>V�i������O�TBwW���4#�X�?�����B�o/��N|4Y�����ۈ������4Yc~G�;�@��AOg�����и�Y�t��eHv�Xu^����,WΥ�F���juk�����ۂ�E�MMMhllĮ]�ޯ7�>�~���\^��+�H��r7Uػw�
s��Ԕr���'�"�!/��Κ���VܳD��8�'-}5�̑9q���$۬]W�B��f^׮]��{+��,Y�)I�zC
���s?�(��,;;7�-_�5T.���?�ӍHG�;�y߽'R Fz�~��;p`3)��;x�����@����gB�<�6�=D�|���� \�*����t�W�6���$Q�~�#г:"�cD1L#v�Ou����.?NH���=��_}�V��
�,�u2.|x"�ɳ��"��5g���ܽ�����J-�l��N���kDCh���g(n=��/V*#T���p�F@9/E+O���v��D�V6I��*���@��9�g
2��U��#�o�a)#w9R�� IDAT�@W��O'����@r )���yv�T.�R����ttt���]�{N��o��AzP��Wc�4p����/������F頤���&��,'^^���$˖�d��C�!�.>y�6�oJ���]��"�
�R��9�?77���i���Q���<���o�VX_�6EX׎8p��(�}|�8,0V������;��ţ�\p�6"�{�-X&�M�y���؃��끷������,Ƹ�<�
��J����s}u"������rٖ�:Z�M;9;ן�Q)�H��0��7���g��l����֕,%�暻�GG1==���y,..VXnR딀�|�$��J�F�h�,[������u����[*��Ͼ"A�Pz��
r����B.��@#��lIh��=`i�a�����E=�Jr�TB�T��~5|^I�I	��Y.��
@.)��?mt4;�r�q�޽�'%���=�nr�����SHB&c��k�&r��cRɠIX��~.�@���<_-�Zc�k�R��"��Ol'j�b��w����2�@P��H��r��R&&&0::
(.8�,2����`��'�hV�1X�*f���]���mmmVc���a�c���(R˥�5-
G;&}�ȃ�js?d�6mmm������w*�lA�L@����
n8�����Y)�%3\v�e��~��㘞����\��5���7# �|�r|�\d��<�l������Q�|�� !����>��H��m�R)�ڤ�4��k���hs����@ʊN��������O_�\)���52'�&��KLr .����'��_�������}V�X����L�@S�HOk����c��S�˲C�4f*4�k�84�ȉL��{&'@������KQ�d{k�N���/�#B���g~~���������(֮]�6B��v�:`�)��a��d� W�QW�l���������-fMMM)+����.H�<���;���@�$?RYkA:��Le�"��U��#d��/Ӱ
?����=�'?f�ȭT*���;`�����~!7��j�qL��\}�`��v����=J�̓�����$fff����M4V�|�롏1P.J*�!%��y4�nPI<�9�G�=�qN��鱏�Es��c"=U�Gs��㯦(�ŧژr����?k��k�0�MMM�wuuaŊX�r%z{{��ի�����6�������\�E
�p`�������k������^�\�]]](�JA� n��1�kW����h�X�jhN���/��o�/���V��(��5��&*��Q;d��������uH�yH4��?RY�������kNLL`dd###�t��;Q	�o��J��@���o��)l-W�I ?u)�ttt���
---hllL�����;ߖ�
�bC�;�y�Bאp�]��;qߡ�)�-.��b�� ���e9� ��o���"��N���j���	t�1X�*��d"9QD�ج��h�}N:��;�9�=������D��'��aE>f�!���k
���ꖿy�E���d�CV=�}��"�
��A|������n���K��+c|����0ǡ�#�j����S��'����N�X�===����w�u-�/)M����������;��e"K��ry�
cA�m�u����
��_��믿�{?�&&&0>>���)LMMaff����������p�人�V$x*�Z�5�ۅLز| YB֡M@�j_�?Oǵ�5w��D(Ød��>އ��8Oǹ�v�{�!��V�	<�E�Etww������8x� �`vW��Ir�/�����!��}_Z`ߕ�zP�$_�qÆ���chhCCC��������2��2���o�ڄ_)!����������
===X�ۋ�~x*�np@?�b5kq��4���Ʒ��5���N��q��d�U�_��_~�`ll��㘛���ܜ��"L\�ߚ���N��}�(YTN�Ĩf��4Y^�d�ezj�\äխ�!K�v���@�7�H#-�l��!T�v��UK��Ǒ�~)��6�#�O�����������c����RǑ�/#Hޗx)�K./}��\R�&I�b4Av�N�l��(��]�-�����rrr���������,�"�����^V��KQB���<m5�.��ʺ5��F�{�
YJ�[+C�-��oc�g]c�>�`Hk
���Eڄd�,
hll�HW�Z�o|���?��`'�cH�z�]�*ޗF�w��}N�
�m"��?��?�300����~,..ba�½o}�[�%�w�o���������?����#�T�K紋�c%�;��No�kllD�P@gg':::�j�*|��_߂J�'0�������,��VDBn��+�_������� ���0==��_��q�C�w�bG��K	)\Ѡ����5�˖@~A�ӮC�!��L/�(EK���,#ˊ\��&���k���d�Bm#/��Łkk+Z[[��\�v
���	�%�/���%�z���PX8Prm��5%����7fq˧n�_��W�����M�v�i8��S�j�*�"Tm��ac�8k��!?̐h�K��6�����4��7��o�>!��H��M�����%di��,�Kpϯ��Hk�6ː�����۩�1�� xjj
����ڵk�AehP�*���"�4�Y��xM"��7)R�F�p�z�F���xWr�a��l?%i}dr�q!�������o|�ę�w�F;w!cbw̰�&�vn��K������E~�%X��
�p���H��"���r_��C@���&�r�8��eѱZ�R���|�ΖKrAr��
�T>�>��v5����04��sr��?e�>�,R��%�������SN�}�k�����l�1�Us��!��<h.A��\4!@C�@'a�!X`vM��y��O�p��\���&�r�)K^#p�)�2�I�.Oˁ�,C�</Q8��ć/.MY���{O���!`��~.���j�-${����|(ۢ��&���ԁ8��E�G���.�
��H�h�@�5M-��R�yX��2C__ߕ�+W�{�>ܧI�x�SyPn�#�=��mtuF.���7w�З��^���"a0�����M
l����g~�Qן�=�
��mk׮�;<<���LLL�"���RSV���%�N�1F��fh� ɲ|��+D,��q��Z��8���XM��~��=<��������%�h$��傏�t��G�g)>�����Ε�"�1���k!;�����ٴ�D�d�����rysm0�f���;i�#R{'�ʏ^w�mO���?�5kXaY.<�<����ߡ�?�38�-�z�4\ɐ��<�ݡ��1��̬~�
o+o�	iV�GY�Ȉ|�uhm�e��)�|giAiOO~�Mo�'o�A�	�#�4�݇B�.K[0���qW�U��%��l��<��{�+_X��󷈍�;	��].0��818�vס�Mll=,�#fi���{b8�"�}�b����+������7����d8�>�H\Nd�=.
�����\V�d]�q���~򳟥�j�����"��sv&��!�v��#]Ld=Z}Z=Z�Zټ|:�����}��E����-�MG�3dɕyC�Cy��Y��#X~��R�k��'���nC6���5�>!kv�A��g�sQ%Wr	�0�sV@�ؑ�*�" }�5����_��Nb���HhR����j�K�s�'�x����RH��Uk'W2�,��N��@���L� �ʦ�5������e9��V,��Ғ
��w��݁�`�Z<	�4���'��l�}?za��>�gÆ
8v����1::�����"|�)���>����;��s㑼��Ng���X�O�j\��&u�^	���j��D�*�o�O��o�hnn���W�X�U�V�k��]���K��P��I(f�H�v�ޗ^wU4`�z?~������(���S�~�����Fh�x5`+�U�Z2��Z�!�+��5�.�JS��)R��R���d���#ԶG�����X嘃�q�qk�π��#��d�F���;�Mc�<�q��b�`��#[��Ӗ�=a���H ��x�0�Y�e	�e^*���&���Cuȉ�Z�%���:d�P�i죦@Ⱥ�Y9��,���>i��6�������`+*��^X�Ik]A��q�ԍsbV�ύ�Z6A,L���b���>33�����_}���ܳal�O��Q�z`�1�'��sb��9��d��D���o��9��=<���>=��"<��gR��;�J%twu������?���f
	�)�Ĭ2���KH��V��K.�CCC��zz:e�����B���p�	�ߋrFZ���7!+�q�"��5V����,d��/��K�_�&���[/�ة�O�=�a�c�<��/G��Sh�)$�>3����+��dJnȥ��v2���4��n��z��������]w�S�>{��u�0��o�>���y-�<��%�
1�$������
�kQ~x��4QfY9d~y���LC��Z�qM�0���W�f������\�===��W�������Dr�i$&��qZ��@�w�v��-�Ώ�b��a�{��'�Y}w�;��Ճ�
ȗ'��KC�?b��xǿ��?��#�K���>5���5k����ߏ���q��?\b�����܃��%��춖W�߲T��N
x��������ku�sY,�l�<�e���f��j�W��_ �O�)$�|9�����?�Z$Wr�I��]��0k�a�mCm�AW�ѵ����O~r�k�ui3�fCz�������@[�!�6	�e��~k�j��r��	���z5�A�Yqӻf�ИJM	�������������BWW~�u�íw�y�[E7l�u"W bڈQ[��<{p������������#Z��]������bJCb"`�8�!4�ɔ�`.���46]�?|��Iן�}����C�ƚ�1���s�f��w临���o���~��Lh܉�+�V������g�c�E���b��s!���O�cY
���-�v}K���j�
��k���dTk�_�(����6����R����L%WrY��ɕL�dh@�cKk�"@�_�E࿈5���i�U��5�
��,MȂ�����"*�V�N~
�\�t�Ѭ/2-�^��e)����бK�L����J%������===p!��lB��~�),�Ul��7[`��v�y�{�m?�ԢS�<?������;�PΨz�^�"bÔ����#YX1���NJ��.x�x�;��1����~�����&�Vᡇ�	`�(p���c���kI1��,��H��6������o���}/��ı�|k�<�r�Ng~N��h�U��Ka�e��D��`,e��e;d�������V��_�~���dƟv��nq��9��eɒ+�,Y�KWh�#�>PԠ_�E�<W�n��,]�"*]b�1�KQ����l����1���	����Z�ܽH���F�����K��L��+V����?�����R�ú�º�Ļ�E�/VT�'��	�)�	(y�q�l�0րYXX�"�E�/�x�2�2�!-o��Ԩ?"z��\��|6l����q��q���all������K�~�dpyB�2|���,}k,�R�-ϟ�� #M�5�>���VS44��mV�Ցe���:��M0���]��Ͽ��?��|p.Kl�8��A�o�,�J���9�\��������?���[�����(���4��0Ҋ@���|�,??bԳDZ��N�6����ï!D�֢�g1�|r�uSz�nj[V�\��&o�rJa_�R�����i�q���DQ��k��;t�����v �%�iR�D��S�y�=�.�)�ttt`ffSSSXXX���Wl�8�E������:����X�n����8�@�mz�v�)���6	�y�DAVpхܢ�(�i.��2ϊ@jjjB�X��Y���e�G]M#:'by!R���5��}*�?�ˆ���҆_D2,,,�,��wJ>��u"d~y5�W�)#ZZ
�k�0YB�V����5pNuq%��;%s�y5ˁv��n9�,�3����$��r���\�G�^{+Y&&&099�d��J�>��\h4���	Y�2B�,�	�Cm�ʂ��1�@8���C����szx>�P?Hv_s�Ҭ ��[�07?�
?1�\��\���Qh�#a���>%�$_trE�\�z ��������>�233�]����'�b__���7��&NE���O!|�O8r�I9�2K�I��3����\�����ӃU��x��CQ��j�}���p�5J<���g��/�|�ڵw?~���~�/Ee*��8`1N�����ה鶣���H�&ȴ{ʫ��J����9O*;��,�_���a>y^Y>]#�"
��.֒�onn�`����4rAJ����K�\�e�D0p��g�(���j��ȵ����:66V�T[#p!+���Nu���--�E����1A���W���	���
Dh�0�}H��_����lt��b����ftww���;+�f$;^ ���^�Y�d����E�U�=��J5�
ïȕ��&S�E���򶷽�Z�-+E���?Q����~���;��� A�;�l��_�y����Ր/���}�K����o�F��v)�FtN�A����e]�{2�U�h�Y��H�NnI���Hb��<���o�~:��s��ֶHى$~����K�\�e٥�@*���R
�|�^��9z4��k���LU��zV�����y>�Hs����ի�e��e��jui�^��Z�M��WkO[�<?Nm��\R
�����w
�����}���F$�t�=���S��X�Rx)ME.��bhtt�"*�+N{�w0�J��VR��k,�'�?�nފ��~�B�Z�b���Xx}	l�B��s"}\kelF��o�
��n���ߏ��!�5F\�"�.K��C�[�T�ϡ(<2��TH��7~�_�k�j��Wk_��R���Rqaƿ��>���&�����^�?��g�Du+��`i�����\~ᒯ�e٥����;��`8��`ͣ%�Ϩ拟��]��}�ﻨA������D}}=fffE��6�cp�M��Q�^��E�J�yH�	k���t�|
�s�k��	��筥��E���sZ=Z�d�x�2�˓kx��
��X݉�	�&����n(w�*�p���N����G��M���Ԃ�\s����<55���y����ҏ��hr���O�6�?�z��_����4�'7<N�[���O���B��b����6tuv���O�z%��4l���~��]��a��a-������{���=y@�Cz^�c����j"�g9���W{�	�V���S*�|���W�l#����ic#�����\3Ae���x{x^����Rhɥ�T*�N?�O}��
���%�CJ�ܹ�����\~!�[ryQE�����XK1v�
�?ZCU���|�O��¤LNNbzz��"�Z�����HO���k�X�-���Xˉ�����h�ľKeCk�Yցz��D�^��~]!%B�O
���R�ߵCÃ~bojjBss3:;;��ىSO9>��f����6#��c�Z�?���\Tz�w�g��g�}E��u/����x������8|R�
������H�=�TTJ�moyk*�YX:;;qꩧ�СC����2�����������oG�΢"���u�v����'�AH�b���R�ۊt��d�܍������,f]���r"�nj�T B픋|k�������>�G����	�766zƟ��R���<�t|�����)�8��>Dv���\~*��q IDAT6��ͼry�%��򢊋��q5}ȟ:��UȈO����5U}�/>�Y���>���~��g1::���
���aff�������bj���r\�"�E��j�]�Mʧ-��@O��4�q�����ǵ�s2���vJ�E�kX:�m|R���Nj�ƤRޛ�^�$ ��SWg[Z(���;w}q׮k�^�r'�&a$���t�@
H�I�&�;���033�?��\�6n��<
�IA<}m)R�x�@d���cO��L��K����
D��Ʀ۾yk��Dcc#Z[[Q*����	��s�[� ��Z��
��Z	@7*��.ݸq���0FGG1>>����֖�51Q$%(���[��k
���^Md=! �z�%B+7kܨvc���l#�.m�4�K �|*w���ycR�?_���ֆ��vttt�ߟ~:>��O~�g�
�o�e��aY~r�>�����\r��Jn��E���m�C5-֣�:)JP+������h*����t�u_�����$&&&��b��+��5@�a�i�y�o��_V�h�8��vp�b�5p��7�xHI��5p��!��s$\	��Ik�zV������b+W��ʕ+�j�*�ٳ'um���?���|�N�5��X�)@����
k
(��q���/���O���A5*�w���1�eVDe���(Gn�p9�;�2G^��?�A��x�[ߚ�o���U�Va���������z�@��Ok+f���h�TF�)��^6oތcǎ��������\*���n�b���!�ki�y�����"�<'��
突͏�����Z������Y�5���XZ��#��t�����_�Z���|���ly	���|H��U
H e���9$�_����I����W��������例��&��&vR�RCS����+o��g����FFF�b?r	�p��˥����g����5�
$,�t}�iy]!%�D��Ԕ����rߐTK��2A �D��)ƺ��	MMM���Bww7V�^�|��zI>�d"�O��3���I摰��+�m�{�{��������_������b���%�-�U����GQ��@��U9b�W�S("������o�}I���X�z5����o��\�A#�����G�9�>�
@v��c�����;���ǎK��P?>�6��rY���T��C�7�5F��@v�"��U+/�
���jm��y�(r
o��[y޴*�f�i�pՇ��|������B�-��X��'��,�=-~K������(�Er�\�U��4A�ob�;���-7�v\�y�����3�x׏���TxPv
��A"E��N�4R�b��@���B�5+��9З���'_ͪ���99������]�_��[��_c5K	����n4sss��fbb��7��/w477��sss���?����p��~�Q��>``ѝ21�b�C�un���>O��D���A�z� F\g`�qdp�ś|��h�����
T�8�E�d���7ӎ�33�?{om�U�	������y��� �h@P@$j)X5��&_���AjYv�����7~���`�0l�`
��J�/�Ґ���w�s��v��?����=�\����(���sw����^�7�5�d2)�?�쫊�+�t�р8�5�8��C�R��s��m�`Z����r�>I"y���_�����k�Q����L$�?'��j���>���������D�?�"��Ղ���_dI$` >t�pr	5jA��sJ������MJ�/��rw�' ��DB����q��?���M7��-��������e�!�*z�rL.��K"�H�%�/]�9�&��sZ����8�y^�\\I���B��Ϙ�8�M�8@���h�	�F�����Y���-dYV}��c������/���%�C�����t��$ax�����A�����}�v��k�������%���-�v������)�3j�������^���K��E���'7����ٱ	�O�����i���ǯ#���<!˩2������]��
<F@�[ޯ���(G�T H̳�ހ��_��v��^������|�ͯ��w��ݜ�\�;]��w�t����4�`�C���%�kf�J�aklM5=b�SM�������Ln=�O�yK���m�A;/~���}��%�4͡��
�镘��|�7�yͽF�w�k�ϵ��C��=����/A�v
�z���:���<O���!��vk��<���<>��x��w���ާt�M/y�ӟ�i�aŰ�x��[�\r�%��0K�T�‘#G^@ۥ�MW���/���'�}�7>��᪦�� ���R�����rq������r��4��i�P�W;�k^=�峘��.)y�������|&>�O\���y��(g
���E�Rg��%��sA�PM�8��_��?�<���9�k�<��m������Ӎ(�x2Y����/��;�y�jz��M}#.���8�7�vߚ�>�S�bu��W���?b���^YY���V��>�����pX���-i��_��$�lI��΃�뤛����|��t����Q���ů��5^����K�cD�:���G��d;�pEof��n���Z�8q�I�����r5r�%�0�݂,X�\�c�jz$T5�5�,?�)�_����S�^�3_�����_��5�(�@�_4���|(�ߒ|,I�2�noo/?������x�<x�o�����yt���\�&�	���0��^�|�R�
y>�k�.s�C^H��ۣ����uE������j�|8r�]�o�7O<�F�,L�y��	��5�;��%���6�����|�y毟;Ǎ��1�}� �筮�<����~
��*�K�x4ra��_[k�zS5�-�`�s�����������Le4�����%ywl-�t�T��tV$�}iN�8)������-�W����?�I��~�pői9��֑o䢴�&N�Q�'��Dž+� ��o"�`�����n�����[����I��o�$�Fv���������r�-���P�:�/���M��o��%/���KeS�
�(h���h}|4����d�8��
��R�/����o�A�4>齧���������pZ$��L;z`y6p�7^�\��_`�&������6�v	�鬨j�y������(�G���׽���w=�k^������Dl\fNT��S�?�y@_*К������7�"3������& ;�����g>���_��˥d�v�����
[�M',<��x۫�S'���I{O�5�;��i���^��dpE���l6��J�����������K�F�����w����k����W!��p�,L3��م�U-Դ���&�K.?|C#2�t- ���/�ƙ3��ޞ��_����-��U�>r�<��4ٴ@Ӈ��O��h�6f	��۷��[o���2�����o���[r	���fvT�#�����[-�?�InF�<�R`=uSE�L?��������{%�ه^��%������¹�@M��Z�i.-��g�@����f�ꫯ.6�l&����hF�ګ�
�נ��G�J ���=T5n�5K۹�G��v;J?2?��,�KfksI/�����s�p���ǒ��_���7q`�ǩ�}��=[���,�.������U8p7�t�/>��7У�H�v�Pg	�iT5�%��C)��(g�Yc_��]q�o���,�Ȼ��W��/
laf�AM�����k���E�볾������r�W�1(�C��t#,c
.~����[�w��_�E���u}�e��jaii	���X[[���,��[ޢ�M�JL-�%h�����W����͟�k���}f�Y�ߏ�տp�7<|�����������"W�5(�8��{ʮ��<�V��h�c��/�>
��u���ï�8x���Ā�/^\��yW��5Iz,@�<F�1���'>�����y�{�9��Dn
�.A#0� �ր�*�[{Ʈ�FJ�/��P��eL}�������.��g�������!��a��]^fm�����7�s�۷��3�m�U��d�:�7�����mХm�%�!�ʓ���e9��ƀ�͵hEQ�YU{d�1޶����G���������O�!�m�v�
��d�y�V>��j�6����}f����_B��w\1���n�.~���U>|博�|�E�6�Ү��x=����v�r�T����/�s��<��j�-m�1~��G�Vk�V����s����v�ry۴�a�5ڳ�6L�v���6�����X���~�w�9���c�Q(&��h`ii	�^kkk8x� >��*�h`�h�}S��	���)P[jҩj�!���,?-��>��׼,?���+����,v���������λ�Z�$�@�Os߾�hi�ډ��y	Ne��, ��6k�Ӧ6��}�}XDP�C^#�F�,*�-*`����E��y ��"šV.$$��}��m��Uc��|~��g}�����S���N����<����g�9���4p	�����4�7��4!D�g	J%(�5r��E@;�_.�o�*!H�O�yW���� ��P�9�'��s��{^�"B��^y�`��w>N絍�?&�(����������amm
7�t�/�S�|�0����KP�� P[j�!M�TSM\��@���!w�9�0�'�����?y�$N�<�ӧO�̙3���)��T�?i-2�3V9�3>�jط�y~
_��^y
�/	�4�Bj�|�QYN��I����Y���K�����7���6��JH#���]���Ӥ��ZT�ɫ�����`��A�	byY�Sꭢ��]S��@�E`�k��G���'	���K���-�g	q'~�F)f�)�I��[�G)�s͉l'��4��+�4���r�K���L�r^�{��A�e�x�x�	ײ,�.���o��Ο%Y:8��}RH��?�>*㧬���&z�����~���8}�4N�:�'N�+�|'�_�4�}�?��8�ڼ�|�na��Y���j*�5��M�{��O*������B#q�e��okk;;;�'�������"���\H�-DjP��*-�<��"nT�O��k/������5U�����NW�IͺL`����-����k ���]#�����kuk��||�Ϫ>ek��j�~��;�A��GƺԠ�<��U�mе���]%�rm��|�a�f٧ůj[U?|�M���-���i��y������,�~�,>^i�Y�v�<->���]�MH�,5r�6����1 ۰���g���SK�>�t��8p���wL-<6`Ӎì1�'��8�Z�� �!�4�=�9�>���s{)����f��6/��~�i�	�e����%���y�1>�/��V�t���*"~�
��$����&n`Xk�����k|m�H�ϊ��C���Բj%t��t\��.
���������/���;�`]'L!<����nA�[N���9p��x�f�v���^~����y�C
��vV�]Z�@�V�<�'i<��>�s/��U���{UY�*.ǐV��
>�������6K��/���6##����,//����8x� n���_�?��*��C�BG��jW���4EgM�_"�a��g���!����_�˿��S�N�������D��/�}(�?�í�V�[[�|ZΨ܅��A䀮JK����@|��>��o^��Q���x�ݫ	�NҌ����@>�C�/^ۥ�V��!�B�Qu��e�U_��W7��H����c��@Eی���1�݀�B�E׎��R;}�Z��4�	��{+��;���;�L��S
{��ˍ$�\e�5�����\T�)�K�8Ĺ�����|���>E���
?�=_�r|i�9����V��x��Pڟ�v�������������:N�<�׾������zZ�`��;�\��F>��L�
TQ=j*�ZK�e������s۫^������vvv���=�凧��1��C�iV��PM��'i�|߽�Z~oU�O��Y����6M��5�������")�)����Gk�l�"�oMY�9��J�}nLdɩr#��i�}uS��3��o)��X��y���|��/���A��g�����o�Y�[���j�5
�v�&dH�l�暎Wi���%������P��{Kߨ�V�����\3���y�+t�Ϗ�Xi�V�v���V&_�\֤��<_u�>��������9xmm
���_	����7�N"�lc�aX\�Z�ɑ�
���E�98�}.�lN�_�ꪫ��̙3��OU���0��sKُIs���n^�|r���F��\
�i�m��
8K��J���~�1�����C�˔��o�m<�*/oȞ�SՇy���4A	�y�~@�%�@�i|�xy	�O_��aa�g�����E�`������_�V�r�le]��DŽ8��s��U� ҄_?�iB
�-�jd��	9���_����q~�V�v/�*AE��\���e�W���w?�����,A�N��%���������_�J�?�8�t�`�@u,@M��]��{��?+�������?�����S����^���Z���P�x@����kh4Zd���KU�{`�9�����.��t
�7o���y�JK��!��B�=��uU�9Y&���\�9��m�~s�_���o���@k�_��ܕ�߯�(�7>F4���d���
���q�?o��n([�$i���ς܍�\�.@��������]�˦z����I�Ns�m��2���V)�T	�t�>�~z���P*d�e��r�[
#�,>����bY��=�ƫ���K���G���)^f��2�i�8��,A���E� ��[����u�Ҋ�t������V���5<������Ov���믹�������8�g���Ĺ�h����yZd��J3,i�ͥ$�s��N�R@�i���_�	R"q���?��p��rq�@�O{.��ܸJ<Rx�	U�*�<�����k���S��ϙ���s |m��~��5~gg8�"tP̺�H�3#�i�����������"��*
��.	\�v/�q��v?��L?�6inF�Or�M�W�Ӟ~Ti���\�Q�?~��;�x4SK'��"۪�!��6i��Ծ�{��w�o
�f,����`ee�>��iO����fQ%Y�#�
����i�T��ܣ��'�f�[:��o���?�l?;;;�F�F�@���8�T�P�Y�iG�5�,��'Q���O{^�������,�o�OSg0��&j�>|����X��7p�-���н��� �:�@:�1�z�)�/.Pq��&�e(��Xe���D{T�J�����?Y�u<(�H�j�������I��97D���5<s
��mIK�@q
H�.�6/Clkc
�7�$@���5��!����[��y+�e�\�_�+x|f��Z��Ƅ#�gA��?�v���#f�)`_D�x���r��.��e{���:�Յ�Gj����xA�y���kB �Yq�3~���<�����N{�a L{@��h48z�����k���w�C��|o!w�)����B��j�&N��K�@Kt����p8�`0�h4*R|�,?/f7?� ����e#��R#:�[L'm��.�V���io�v��q���-��+B�<�==�P|kV �%�=c-l��X������ېM������1�>�B�	��M���Z�S`X��� ����Y$5�k��iGj��π�o�Y�`-�e������l�
�Ɗ	X����HZ
�O�4:���:��vY��'	����\���\+����9�_� �������:ަ��pπ��,8�Z7^Bc���3l\r`ɭL��/-�l IDAT��t/]Džb��e >�c��J�P�,+�!�K�e�
�m�0��W�������P�<�m����Rs�A��*�Bq0�,�]���O.4ֽ6ːY[�#�c����kdR��x�B��/��`0�'��N�L&���#�51���.@5��j"�
���n�^��g<c2��|�	������|�7;i�|��	Tjo�v��>8`!�2�p&r���+��-�U�M'�Y~
F`�R�eY�1i�N 
�\w��.�@K2` �	Dp �a2�3��A�BS�7H8peH
���v/�k:G�(#A�ZD����0�r&�:�(	Q�e$��8	�0���blAP���`�Y�0M��)�10i)H��hD򽑚��5�$�Q_�Ca�(r��s!41�5��č[�p���a���b�6�����w�k���V[��\��0}�R���R=M�h���t�uQ输,�Hx��R���`l�u3w4n�₀���"��8���ԦKe��̋(���������Z�$I�g��_�9��M�|���}����1�g�Z^��`->�Ƽ���ƘB8~�4�{obMz7����+0����qN�P�~�ߝ8s��
�,��^��D&5V��b�i>�	߂*�s���%���t@-p����E4Q��i���������/]�����s��]fxƞ�!К�Ȓ$�?Ir𘦀;^J�e��,��#�v�:��w&EQH����7Q�,��i����T{i�,�Ņ'���0�c����I���I��K�`pk�k_�x4�0��V��@�h�@%��bfY$	l��1�8&�8�����v/j�0���uv�E�hAV�'w�1A�h�6�M�fA�	DL!%
��9�'"�%	�$A6� �L򱜦�s�(BE0�W�#��̂;
ĕ�"�I
�<���O�)�Y�-�/��Y�
Mw�!M�q�1��&Ir�Z�(BE�����Tp<">i���%��Z�L�'�HK͙��x]ڳ�4���N�O��i���&�	�8γҥi��p�#�n��=V��J�(�Ͳ#��&����t)�φac�w���5-L�P�~(k�ɇ�q0��8�9MӦM�\-],8�ӴTR��uP'Fc�h �"a�F���-����Q"t .d`�2KP��}��~��
����@"�4i�d2�Ad� �c�q� ��M&�Y���L�0���[J�0��8P�a��@_����|
Ü�N0�Rp��'��I�^x��U�:�0��8F�$�l��$?nL��4��!�n��Va���ۅ�t�Z[�\X�)��=˲��1�h3��FSk�{F6M�Y�όƸX���З05�\���S�6�mD�l���Ӂi��f���f�#���v<΁�p�@#�L
-v�j!�tt:��\��������k
����e�U��]�"r=�lC9���A��x�eH��s	�p�l<���M&�&<j�5��m4z=�f.�9!�bo|}���/7q�&�5�J��B�?WCi���#�M��;WU��=�q+�&�7_�d��p&�k�բ��p"K#��9}��|����Aj���T����,�dȕSRy�'��Z-��m�F#4�f��g��i��G���g�[4 �%�$7��fa��V����D��A��̏7�h69pu�5���5�kL�ީJ�F)�\��9�7���ŋ��4�%w��8��q���
���F�x�x4BLj܂I��ҿ�S�
�/Ü�&�VMl�V�V+N�MQ��ј~;�
��	�?i^�xGB?���C�r��PN��N{�9-�q��t4��a�Cd���-�!K����rZ�hi	��
��UD j��nA�}w�5u�&��6#��E������[���Q�1��
Hsk��%�� E��m�������*��z�@ha9p�H�e�)2 ��C��#CN���Q��롹��py��2�nh4�F��OUn�W	R5�����y�`
�e;��L�ei��ǘ���`��#��͵���q)Y���C��Ecy��UD�^.05Sw)���~���M��HS�,�C�u�H�$�c��1��������AnA�H���&��
��B��j�B�C�IK��%��Q��l{t:�./��%/�=�n�@����>����!�@M��������}�+^��)Y��,���-�@���D�]�-�
IK�Z�!�B���Q���D��F��A��C��E��E��E��� FL��S������xē��EĿ��_���O#�c$�!���`���.½=�wws�hT���C|�|���Q�h j�Mc�����;�\h���8����
ht���,FĿc��8�я"d�!��v0@2�����H�f8��s� I
W�Z{=4��<���r��m���M;v��[}�h�!�$�)�3��%�v��Ϊ�a�6z��1�_4Q�>R\L�@�Ӂi4���?��z��Ey?}βǏ�<��_�u��'a�Pi��q�ux�W,\���X��p�'N�k��4n���E��E`-����M��_�5�.����ۑh͈�Ǐ���ދ��&I�ɤp3�B�t�����s�����hc��	�V�N�n�s�@�9���\
5=Ωj�ĵ�c�p��w��!�F���4����~���Z�b$�
�)��_�p��[$���G�F�N�n��e����Y^Fge�^A�_��o�I�x��}�V�����\�����G?�[��.�++��no#�݅��+�	
W$��pW!�~��A��Asy��e4���^YA������i\�W�
<�|�ex�e��[k1�����],/#��F������ w'h�	���E��`qp@�fkk?�0>���ቧN��FI��~��!��O���yg��/��I`��R0,'�s�����+���3�L�����Ǐ���8�7M�$��	���,��x!R��9sG���>�	�t�FQ�R��A��+�u��4�p��<����G?Z�_n�0l-�Y���i����b��o:/�_�x��F�FKKKXZZ���q��A��ߨ�0B��O�����5�@MD��3�Z�1�[�szӻo��W���?%�>���q����6��!MSc��i�:"�I����D�[�̩Ɓ���K�w�zkk��-oA��Y��2��:`
nfڶ�Ez��y� px�O�.��R�����a������-��b*˹`������\^F{m
��5��^�������������*�'L\Uޢ���n��Y^�s��n�q���گa|�X����Q<	K�6�^��h�k�Ү���{{{���?��o�?����>��������%��Ń���z����Ey��G��X__��7ߌO~���͢(���2L�U�7�Z�.8��� ~+���(I�����ѣ���?���/i6��
�m4WW�ԟ@4��q�\6���H�G�F��;I��c�>}7�|3>��O�{�"#�&hM��y}��@=t�~�����z��4�+++X]]�����������r��Z����8�Z�	��v��'	v�[����n��5�\�v���`P�	�%`�	-hq����O&��� ������y�R7Z
�m���v�Y^F��A,���w�֞�d\��Ң:c��y���-j@Y8X��8�,�蓦)=�x��>�7�`ҥ�4q\�E��%��fa��f��������!4WV�����X��ҥ�h@�\����I/��SuL�TY��ioz����G��nq.� H ay�O���t�$�gCeO&�u�]��۰���Q�b����ۓ����+��܅8��
�6���G����>Ӕ4�0�u���y��C��tN����]9rw�qG·4E�ey n sV(*�����k�R
�>�qH���C4�;vw�q�9�)��K��R�%��a��Gʷ���l��c���x���
�~����[�cI���SzTkK��6Z,��Y����5��k�A�%��n�
� ���"+���6Z��������������V�֫��d��Z�_P59rB�y1r���	�r���]�yϿ���k�ԍ"<t�$F�`�O�|��ň�?	<�@�nI�%H3�̴K�=]j�f����
�++x���߾�3�(@|mX���O�����x�h�r��\x!~��o�������j�zq<F�Є�Ⱥ������2Z�{����w�sƟ����qq6����>k����E-2��'��=��?`0�o~3vn�Q�	;��}�p�Zx�8���������F��q�Q� �24];dF-	T���ݱ�3s͐�%.��@�쳜�}K��p�8u�����>��,G4�͈6��BҢ�i�{�0�{��LVh����%�_J�9i0`ss����r�b�$hA�A�˶Eυ�R���#��"`����#���"��������8�(��)h�>"�W�}�<e��]���.z�^�K��r����C�\U���t�0FY�믿�����u�r�^����j�&N2�,mW����Ml���0
6�r�L�C�c�>[W^v٧���;��	�9�!�#ͺ30���]�WW������1����Ni�I���ٙo���4@/��h�}�d��S��֝>q���-���
�����g7A���1��eu:�VV�\]E�IO��n���vÁ�f1��N�U�<��@��?�/�S��^�?r�;s���ȏ�nl�w�E���L�J�J�x}A ˲⛀��q�8I0I�b�\-���(��[b�Δu��nƘ��y�%����0�
m�$��,8֖�I`��%�3��5���[���}��n%je�$AE�+�p=����?�W�q�JW�����($/�2��G�������a4#�L�:Aٸ9�*��Ǽ���Q��Շ��>�Y�����`9ޢ̯Z�$�愮���c��瞟p��=D�T�B�P'��Ξ��]��=���s��7������ �8�g����5\K�c�Α`�A��F����
��;���R��M��@�G{����c�,��B,yM����G���>���`[-$�V����6���h��n��������:4#8鶴g�����ު��y��Ydf�ߴ,�1����Z�F�
3� �6��եh���|�q-o�64��0�c$�c��
���0+�K���
��v��@4�"�l�-�6A�`'@�����P�]%&�	�(*>i���;e�""@�	�몴���	�k�yB	���C�b<�����cww�����/�y
�L�a�im�~�l�~&yMռğ��x��x<�`0���n�:c�h:E����4�#E��H!�k�{�N�ٷn���Ѡ_��>����P���
���$q+������e��UcVVV0�h4�����"B`��H�?��4a�ܤ�h����5�x�K_���_�/8�G�i�4@�-�t�h����z`��p�~~^{�/�1I!q��m��D!<u���������_��(����W������N�j���x(���aP],LE����4E����KZ�\�/�V�������|t�`�
��p��Q��#���-'����'^���0I��fnG�$IJϗ�%jf29�8i@�x_�~��o9H�u� �n�D��h4��0��Y[�/e�|��������
im����gIm!��}looK�h����[Y�}������&:��E��c@W#��o��T�?�T�S����j*�&k-��cL�;ʤ6�sV���n���2vvv� *�����c�%�O�%w���n��v����h�z�ó�Ti��_�h����J��E@�
����o�'��)�;��m�z=����СC8�������p0�
�|�c�(B��F����gq�s�I���kR9��Y��?'⅏�>	�x۩��y睇{�������'no#
C�A�Ԙ���v��.r+�L&E|L	c
�	�H�w���s��i<���r����=�ף�iP"h���'TS&9F��7�C�!s��I~r+��k��Ec�L:��uHk�3ڻ���������2�t�]�i^RxO&�W��'e��y|����͉�|�O���~��x<����;��z���s�lИaer�5@9�Ƽ ������t���RٟsH�����}v0��1
��j�_�Z�I#�$��1
��:Z���c"�_�AA���A����Ź�Xcp�+^������*�d���ߤ�$-��"h$5�����7�'��4����p�?$p�	%Ƙb�v�0��+^����aio/Om����F�O{^����;~��.I�R�'ވ|���G�[�:҇o���GcO+_��Z[d���zh�Z�sm
�w^t�4��`�YJ0L�������^i5e�o�`̅�Q�kVD����[�B�O���M��1$�i�A{2�xo��8�h4���^�Yb���P��S�u��B�z)���܅�4���G+C�Q`�b7������ǎ��M&y�.���cNf����K�������͂��~��^Z�w��m�4�>�vcJ�"�������q�m�}�4����5�@>w%f��{��	���(ѵ�q��{y��.�-3��]z�����j�!�g�AC���O2;��?	m���q�����fI����,XBnU��_H)�8(��x��OsCù�D�Z�6:�^�9�.i>�?����www����3g�`ss���X�5m-������3�`� ��n�������5<x��@�MZA��.MS����,C;s-Z��vQ������$`&pD�{gΜ��3g���[��*�?����
�#�8p=g"�h��:Ik6�h��0Ơ��#���$H�)mBD�ð4F� (�G�����No�f-^>�~`��A�y.�]T�Wa����uε%sB�ISX',PF�{������x^0�T	[�NKKK�Elmm
�f���I
�T~�$������ӧ�������Ba@ V�Viup���p�ӧO�{��]w�c�8.6�+&a��A���cǎ�_�*��_��Ь��cU�x,HS$p��h4*,f6I`�E�&�%Ә���!.4�2F�w!w��Bއ�j�:���<v�!+�~����O�:�gM:�@M*1!�*E��O�@#�چ����GZ��hMj��F�'��ko��k^����G]�gP�x���(PE\+j FQ��j!�t:��$�4e^)��C=��G�����ɓ'1Jf����#�Ŧ�n�IOz����㢋.…^X�OӴd	 �7i�H�I�+5�1�Z�S��D�� l���9�x�y�5�;;;8~�8��^�}��x�����[��.»Ey�(�s�����.��"\t�Ex�S�Zr��".4��B�J�c�ŦZO�1�/\)Y"��|�kY����|���B@U�'@m�,|�Nh�TZf��8��dv77�����G������կbgg��,�����m�o���.>�g>�x�3�YX�(*�g�v���6o;u���^�u�]��׾V���n�(-$dQ��=I��D�N51����,�V�����ѣ�����`8b4������
�’i�9��EJ���rʎsA��̪T�|~��=䣿�|���tMf_�<��7�t��1;c�[g����j�&/)����td�ڌ~k�9. סؕ��L�{�IU"��HAp�"�(d��W�1`����s���9����b��)D��*گA������p8DE�N���'A'�---�<���0܎�Q����*ʒ��}��F���ƒ>�[o�w�y'N�<��` IDATYh}֓Ei���N���Zk�uŞU<��V����%t�]��8r����2����yQ���i0y`.0}R��?Z:O��P��Ŏk��EB��sἤߥw3M��1���d���6��n|���-�܂(��iC7����ڲ������Z-\x�%�,�U��L��}|�����ފ�p��6O�G�s7)x�Y�V!r�<��E��X��h���]�<yw�}7��>�67���#���@���;k��3�}����Xmշuٍ��6�w.?&�
�t�Z�Hs�c\��W^��G���4�y�	�K�]%!�6�$�O�TF)
w�����j��E�+��p��O���R��sf7�s

�i�]~9��o�
�Y��vl2�`{{_�����|w�q�vvv�]����؀F�nHƂ���s�~0A�И|3�V�$A��{aVW�x��7�*��0///��������໌A�6�����g?��گ-�;^W�����C=������۱�����]|�h����$A�e�l�8�q�)�L�O�ƘB+j�E�1�9��w��h����>��!�Q���2nw��;�odI�/�^5K@���Է���ⷆ@|�����q������=˳!�a�E���7���ߍ6�3�8�Ё��͈���P.�P]!mr�e�X������ >x�'>�k�$<��C8r��~O��E��#LDI���vɱ�M/j4.�<�A��i-ZA�Ș����$�[\P�M�(�fc4B0!��Զ�\�v��Ӏ}��K��BC�}���~����4]۸I��r�ju��oi뮶�r�F
�k��Z�i?$'��	ɧ�?�i����@"��Fa����j�'�-#���'p�w�_�"����������A�2�����B��9��s2�z��I�V5���M�Y�0���/づ%|�u�u�Pq���K�"�"����Չ0�Ӏ6�0��u?��Udccw�u���/���������~�Lj�Q�"�
�ؼ����@��9��1��f��mc�
l���0����������|ɭ��1��-2��h:m�����`ɒ���ԄʱL����˃��l�0N	I�*�����k�,�����ǹF�YY@����i�K��LI��x@�c@oi	�V]�Dm��X�q����� ��"��E��h: �Y��	�lH8�Ʌk���$k�F�n��Ήx��&���p����p�h2A4�����T�>o��@��9n	0.y�>���G�wͅ���1����'��T��j�&/Yk	ԓO?���7���j���8�>Z��b"��J���/�)�� �ӁFQ�H��}k�����x��p뭷b8b�����1i� Me�4(Bj�ŷ�h��ovcc�qn��
ht�غ�|����~�f\G8Ȕ �|��F�HZ��Շ �`���Pj�y��c�p��A��px<F4���eh�i������ҽ��R
P��ʙ>J���6Oo�4G#4t�c��?�%��?�y��3�Ԗ��e��L&��j��qL`��.����w=!d�tG\zʜG������O�~�e���H��Œ|�5� ��4�\�υV���N�ey�Y� M�w9�w�b��P��k���1h&	�i��+���c�1�[	m�~�y�&km�8�&	Zi�V��[
MP��N�=�M�
c
��b2Vb�[�H@������0D�	�6��i����=)��k��|�&��X���w�ƷT��9�|l4�L�,����
E�2r_�@y�:f1u�Q�����l�һv�I�Z�I%k-���oc�����,@<X*�9Q�2��8�j��H���G�ѷu��|��<-]�t���|ww'N��}�݇S�Na2��]���x�F���eE`�T�h�����P\Gߑ[�(B8"`��
���7K��}��<��q�?@iT�2�������O��}�݇�'Obgg����:�9��$�8-&��J�I~��\�N^����t�5"j4���p���>������0*�o�ῦ�&K�d2)\1F�� ݀��a
��9$}т�i�M�oh.@r�Z��:AZ
OR�N|�,9�|`-��7p�0ֿ��Hܵ[�	WM��M�A䄏(I�H��k
e��	��_�z����8F�v�m�)zi��������y��I�\���fI�j`*��?�p@���ʻEs�ʵ������m�ز�n��}��k��+[��~N\��B�ߣ�[9�Z���-��������ȃ��н�j�	@-Ԥ�!�1B@	S��䎵��z��W�JW�*��
��u>�T~�
 ��\�����>��M&0q���d֖�����Ŀe��y�@���{�5qL&�hL&�֘��_\�W�N���"'��;~��x<���6|�A��c�q�v���eh[���wa��&
����$O%Ck�Z�$A8� ��F�\L0�������<D�����]ޫ�dz�4���-�E~��U�
K��J�6;&ۡ�SH��F�1��5���Ƙ��GB﹦�ks��ݧp7��:M��X����@Y .]��h�[줱מ#�����5<�Ÿ_�q��̸���v��v���z���1hN&�pD}�6�X>m��ߟ��M�7��ю�I�n�4I��in%r�S!jV�o�7|hZSt(������ (�������� ��֛��4C�PS���?B��u��5�Yp�cԤ�4���y ~s�&7�s�:_��=`,?�o�C��ӧ`2#�c�i�k�1]ԥ�WMc-���Pj��.l��$	0�$	�?����
��o|�7��FZ��,���/���Be9s�L�Vp�x�LSt�@�e$�r
�����3�F���Á� ������x��Z���7�Y����>�)�ۊ�Cο�Z:��$j����wA�5�e9�$i#���SM��#�^���#���{�ͅ)���ЄH5�8�7i�ks����wJ�|�gR�@��i4d��
���5��A�4��;�[\P�ƛ1�f�w:��(B/�p@���ohN��]�]����Lk~�`�,��q� Mq�2i���970^_ջ �Ĉ|�20�j�8�G����J�{H9���s�S-�TP-�T����翅��"��罏a������ܑ0Tͧ1eW!�I�8�F����>vvv%	.J�-��s�J��Z=��w��nTΌ�; ��E�G�8F�4Q��\$ؐ�O+H��8���t@A���\�vvv���1�L�q���3L3J�H%�;f-��B�B�&�Ȳ\[H��q�g��c�K�|�3�w3.D`���d,r�݄
P���+?�"͒����<K-5�_Gc^����%>�}���
kg�"��� �_�ŀ���4�H�s��`���f�V���[�L��U�n~@y��}%~����©���G��s@��������4�M�@g}�,C3I��X�(8�'��h��������ޔލ$A<c<!1a]�X8�Y)���H��]���p��p8č7���>�dž���05VQi�kkzS-�$�k����V�oB{v���L֍�cV���qirg&�b�R�`�����&;��}��#�Xb �|A��t�����2O9���iE�2��͜&����Zjn%���"��e���1���
!#HS�Y���
�����L���8v^>��ZD�K/����w�|�T�/�˅E�� KzN�]����8DA�Q�H�6+�̉4�䍼�[$@"�!�-i�	|)�-DR8Є���.@	r�C}���v�ׄi)�L@�i��2E����|�ҞI�L��t|���pilB���y���$߹��l6��)<��.����߉�KKع�t���1�,���`��%�L\w�倎��||�N�vw1��EbLnѳ6O�J�P(.x=RIS�43��������qK�s������3���Zkj+@MD�P'��gy����{~���>���?�C���k�u�y�͘�������YgY�`�F����W��S{{{%m*_��k_4U�ô���i.	i��f�<��{���/v��	���Zr���ܷ�|���7�h�G��z�E��As��Z���v����,p�u�7��ݩ�������*�EQ4#0��~�^J�����8�<�"����8�^#�Cܣ�	�`��^�u-CW/iG�V�U�,5�;�(��s���f�ٶs*4�,��Ż��v���9�3v���"ï;?c�c�k�e���" �"<����cz�"�I�Ei4����8r�-��׾Q�K��hsFQ6;�?�� )7~�G~���}�S��t�s*��N�͚��Z|��i�p�
������ʥ0�,l��3�B@Mj��2q�t!��ԧ>r���j׿�u�^��S�J���?�ى�[���b<YO���01�L�8�����bbg���I��	@)	e��FyzG�I�����S�n�`U�+���3�]k���l�Y�Ծ0��j��B�
rcᠫ
 �8��)w�"�(��할MJ�X��(m���J�݋�Y'p�!�'v��L�4��/@U��%�F��p-�A�P��w
�}�_:�`���]TJ�1�̺���L&Sa�+>��r����i���P�9��I"��?��r�,:��[i���R�"-Z��j���T�(ƴ"k���`0���:��|��G����FE�7����� �	�Rx��s���c��>��t:ņ��vQ�������yg���Ɵ����Vq��
9��CY�M?5=�j����6r`Y��{��p�̙�nnn4�W�ٴ���-��(��Q����ZӢN��4���I���n)CF�y����GuI��A�"����5d�.'��G|A"W�ꃏ�G�F��;�}���l6�u���<��g��� 5���������e��H��U�e�ˠT�K����Ȳ�F�x&U���k�9�4�8�V8�V���5'(9���Gn�i�pz�E3φ��?W��S��D��<��Hsu#�biȊ���	Z�\�t��5����w�+���V���& �q\����W����h^�(�����=��|�#��?����;��P�^J�����xƟ3%<���-�����#�����p��/���kkk�������r�.�#L�P	j�&G�P�`�m`�m�u�������ױ��^��}��(-<��ƕ�#�iȥ���������DZ؋	�m���R����n��m� ���sܟ8/̨�P�.+�km���3�Y� r���N+K��i$�=��2��-�~�W�,G�	��8��|C��o
ﴸ	(�q�&�X���WtJ�i��5��
K
�e��8�d2�h4�x<FdzY���kBʼ1�5�^aP��|�=�]
'>���jR���퇊�^�E<	�/	\�}��P�N�u@�;X�>��Z1�Lp��	|��_�]w݅���ĭI�$��J���{�5e&;/���\���%E���vQ���k3��S���ߟ�?��
��t��V���@MS��'�T���8�ޫ^���mooY\��!F�ь6iQ���|�쌆_)����$}��2�7�r�]Y��*���-5�2u!�f���y��� Ne���V[����H�����n��F�˰l�e}�| A��R��[j�Y ̯��4�dI���x�8
~��%���i3lɢ �'*5�ƣ�?�Մ	����<��,V>�|�c��}@#ѥ���w_s����fq��/��0�N�|�w���#�t\s��4���G����jޝ�O��k�%�L��DZc���C�ĉh�1�n��ЭM��3�����������>.hisޢD�"���m�۸����������ot���^�����&�۩��8�Z��Y(���|����]loo���w�@葒���[T��1��{x7`�����&�vA�}J�8��m����Zr���\��Y:��Ʌ�k��.����8M�[�{�EA��)��18�`�o(0#,�������ϟkA	,q�����?�� ��3�uKܕ��?M`������������ ဏ碗B�^*_����4.g�*��(�<�}��Q;�NR�Z;�_��	���B������8��-�9��$�ā�Ϫ�e�PR"��F���˖�-w!���s�7]#�=�L������
�����e����$ߑ��?m���6N����(����$Ⱦ�-Q$PR���6��6���齮�-���jP5���$̌�뮻�OHA@�疰Sn�M9�i�5y�}��8oG��F���sc;�@�&{���������i�i	%Aǘ�]B
f�7���}$����#�w�����QPP\�՚jҕ =�ۧ9�.<��1IAށ�:�I��-ŹQ nI�K�&�]<u*��H �������(/}�.�K!K�#������ܵ���\C���N7�*	�J?8����f~���������X,�h����\����	����M�#����s�:�b�; ���}M�x��O�d4akk_������b<ä)2���ڲ�wQ�<�'hqe*���$k��)蹐�y�5�\����G�N��k�k!�&�PS�����E%?n)��MRҽ�/�Rc+�0}��oZ��Y�&�*`HDBBI[�4�(���x<F�e�y��b�Q�����r��NI�K��X�e6 ]�v�Z�T����tsR�lr+���ۘm���J��V��7N��O��r#5^�uB#�p��n�[��@
��D{W8�xWFDt�Fܕ���Y��o`*��4��_0:w������ܢ�~>'� �ҕ��Q(w$��觧
�}����(�P�1O㖝�¦6��$)�X����������"3�$�5IaBZ)Vd8�̙3���{�|%
�c�q<���H�	Q��Ϳ���+�N ��c�|����O��I8�������b�&�t�1u*��=�@M�2mf�_[^.7r-���4�������~�4�/����Bs#�@t=0��<�
e(IF#��|ٍ[4��f������A�P�@�S�hZ��ֲon����G�Hh�AP��b� ϒ�3`E�UR�`�����f�|B@~�os��I\��Yh�'P&-E=�[j��5ڻ�YL���r	���yB��-�O�~Rۢ.�>� �;�e֑|�Zh.�i�O���7�i>��W|����r�8Ϗ�.6R�N�l��>~�a=zw�}7�?^X|��GC�ĕ
<53)e&�	�$���S�f}�|����yp�������8ĸ1H������?��?5�TP-�ĉO�qj{{f�(�|���#�Z	ʪ4��4��"�A�X�d�oYO��BP+�s��GE��8���8|�0�����,+i�YW枧~�o�v�i� ߉�%�o�C~T���u����M����'5v�,�v���8���q�� r�9��]0�>^e��s{)�JVn���BAV �/��[�.A�I�n��B��^�4�2	�^A�}k�e*k�c��먲�ȸN>��[���M�����NQYU.@UV��hTdk�sj7i�[(��)�
~
���O�+4�n�r/���p��)|�+_����%<��C��.�?�8��F�(�7l��W�{��@���i���&i���w
�o����I|��HI! C����n�*k�_��@M�hNJ�o2���-o��+���z�F��A�m��M�����6����IZ�0Fy�$�4�2G���j�1`
dWWWq�����#l4`�(������湧���.q�ܚ���2���L"�"D�M���#��,�6�)��zw/� IDAT�Q�~�\Ć]E���q���_�:L������z^v�/mA��kP~��)�L!h4����S��@}��#�q\Xɀp�'>�x�T�4M�|^��p��Lj�F�rRe�S�	;6�
Ur3c)}l�v,b��ܘ4�2mn�~p!������3r��.[��1D9��S5�-N�=@j��](�8�����<�������?���]\��3� �cY�Ӹϒ$s����9J��]�Ȓ�Z�vcG���)�,CS}��H�PZ`4����}7����+R��`��}�T�V��@��)ve��zx�{��:oEM����X�v��	����������e䏞��߉��m�C���B�$��?�m���疠�k��Nwt������=J������$Ss�����++�k{ώ���4M��xY
��}��
��2cL.��Q�	���ϟ��p-����k�i3+�%A�"yGe6
8p+++��`��"�\����l��X'�"�B�}�f�xm��Bd���рi4��]�y�$���@wI(\D��g/m�i@��W�ǟp͸�������[ˤ�HsO�\O7�}D��h���%
&�O��Wp_��N7����U�9��~��$�.Rӄ�%�����#��a��
��m��>\�$��`0���666������D��X��C0� ����4ڒ�:�"n���c&d!�a3�*��
�LW�Um,Z��фP*5�]��{-��v��/��`YhJ)��QJI��e�e˸,af	I)���|�o���1������w��iLIg�u׻7�ęb����ާ�J����ѳ������b��<p��6�$��>����_��GSm��H)�=�m�}�qtl�+Y��B�P6
���cbb/?� ���e�.R ��:y��S���31F���hhʂ�����;��Ώ�J	�p^���K�-%��\�RP��0����H��̒$E����9d�i4������<p��E��!�}T<~��Y���g�/��!_N�5/��|�zձ1�����:1�Jc�^�:<�e�������
677���G�d��Hwu�V�����氰��f�� �m��>�0�ǩ�1k�(:�j�		d�u�AW>׾/Rũ�@e|��q��8��������?��>���������ut:�|n��x��y�@�E镢y�S?��q��ρy8ļ
Y��>	l"�����8SH}�G%���Rȩ'D�Z4Qh4���J����j�꿌�۟׼N�����9}K�ϩ�n�s˟�t�$�����L�EQ���ΓE�f�z�嬰s�{��$�_Or^��L�M9ȽY�)���yzl�(��!��4L���zcwec���������fgg177��cC�!}����C0��q�<�8��yI��� }H��.��?���]�߹ao�uL1��~��S��3��/��EH��K�"A
���:3F�%5�g%��0������bqq�v�Bse%��e ���0�,&�ڮ0@�Y��o�"
Pl��
(?�j����u̜q����N>9��Y�V���g��^�zJN�牁V��h����E���1??�]�vaii	�v;?7��t�(��$Q��;��G �S����o����Z
R&&�^�ۿ��]�
1 �L�$�4��z��8�q��1���*�AP��E<����W�&�V�<=^F;�(�>'�
��H%�所3�I�}̑�7��e��$�M�Y��y׋\%�SPH�����V��bZ�HeF�q�o,��riE��yIS�i`i_�R��������,��FS�Vr�x�u�=���q���5jq�j���)��{�"����m���^�$�@����Z�<DIR�f=~���Z����di4"��(�ڵ�=�ܻD�:Y�'''155���9�h�.�����Z�>)h@Np��S�p��.�%����s���ވ����+/�������l6K��K$�������-��"�~�I��X��ۤUG�$X2�|�Quxp��_���m#ˋ_�bD�.�F��A�� �T	���MN�E���ЋK��e8�VQ�VQ���4곳h,,�>;�O/q�:�5"����666���RE���q<��2���Ud`'R�����[[[�<�77Q�tP��Q
CQ���0E�+��(Tڼ�JI�T��uT��LO#��G�����l|�(X�)���j��lbkk+=O�"I
 ����\R���	xN��zv
V�5R�T=o���E�����K_�#�jD�fޚ8�`��Od����d�IA�(
��9�t:k:���	�hV\	�iui-��e�H��8
��"@�*�Y���\z:L��ש]�`���/����m��j��!�Q����f��C�p���h�L�$��🔐llF	S�(��d�(#�#1y�x_m��zI�#���z��������fgg������`�;�<�� Np ���G���BJ�l��>q�U���g���>�FJ�H �V��_�f��|�MZ��a/�2&�-�^� ����p�u�$��@��L����W������Uغ�n���0D�塮ds�a`��3(��oO��Ǚэ*�P��@}v���0=�����(��jZ��O�W���©S���H�L	��"l⋇������8�O��%/A�ZE��/G���P;q�(B��OW�����@Nw�9�A�&�6���P0m��J����@0;���*���ggs��$�5yQd>x���������!ki2��R�r��[���:v�ܙ��x^`J��K)�� k���
͗*	��i0��ӎ����U�{<�c��G��}�]WIv��B���4�?p
�I���]�:�,�RA��6f.���8�h[��E�^/<W�еX�:���'=\Y0��y^��=0�E�ZE�ZE����q�*�
a����K���#��ʖY�5�m�q��x%�"'	�(2�8��g^2���y��s�(ۥ����s���|��\W<ؗ���i������{��p�/��
@E
�'��(�p P���u!����n<p����sε�z=almm��j�A��R�j�*^���k;�ݯJ�B��}D�~nŖ���qz�������j����y��>��!T���z����8I�`�F��~���,|?剒0>���K��&������<'9+��϶����j������Ǐ��n�c�>^�/�~I�h���̦Ds7;;�{�8Ʃ�%x�
q�*Q��T|?Wȓ�Y���hh^3j
�zA�J�
��@ej
��~�L�e�9�9m�~s���N�:�����@Y�d�%ּ'�j���رc~������=|�V+�d`��7e�"��+Ct�لO��sZ��l%I���~q����F��Iw��U�
"�ࢁ�@Ϗ�2
eS�X_M�RdhlPJ%B΅�.���4��q��G�O�q؎p�2���j����2齣�@���Ν;�����-L4�"@
��R�־+�+/cSd��fُha�(fي��^��ʔ��s����L,��<�KÕ��ʺ��;Y���i4y�䩩)����_�����G?zR�?$���-����V��ﵑ&�������)Nrɼ��a��Xf�p����ࢳ�:kY�x���(�wY��/)<y?�w����f��8��z���ʵ���qw�˾R�`bb�����������<���>y���4?a���03Z��w��xiZ�J����񊷼�{����Z^zm�^���jayy�V�~?��I�L�Á���#3�h�gl=����Xn!��.��џ�9���oѨVQ�,�9�U�Eۦ�R��?���W�������Q�n8�Cf9��1����U���������o�c$���+�L�<�$I�J�����3��+^�
��WVP�}Ԑ����|1]g�J��34'^f]��I����E���psI�
Z���z�]�<�KU��Q��i4���6��#�
&
PY=�@/�?0uϐw��Wz<��X�f9�B���!)7�1����a���e/{Y�q�&WW�P�����<Q�	�+��\qcs����M���~�M��(����}t�mx�.�N���O
I���cн+�;�$|�i�a���g�;���k~bb���y������S�3t傅7��
�e�H������w��)N4�gQ�x p�f\������{�w�e{����ulnnbss�N�Ng�7���-�hY^h�F[�
�U:Q���0D����7"�"�˷�-�0�@V	��;�<
*	�:�w�j����P�lI����	��zM�umm
KKK�t:i��0D%�P��4n�߇�$x����}o���,,G�m��7�m�L�F�����س�q�o��7Y�5�/?<~��l�ԩSX]]M�����1|Αg}���G#���h4�_�z�ر333C�;<Uך���6>�o�ۈ?�	�:�j���� ��_��J�t��E�$
����ך ���ve.�՜��L�$�a Oh��:g��M�r�8���H�R��;).����6� ���,^����3����Z�<�� @=S6�����t¼B�wn���i�8���Cۘ*�c��>:�.z�6��M$���<�<���#ʼ�<����$ρT4���g(*���L�V�����^��o����_�ː��!���Ã�8)�S��y(��w�K����Q�f�]wݕ��U�Z-OJ��� �ف?��7�x�mι��M/���8�ZF�z��vQ�G�/����N}����L�r���c�b�ŷ�*��	8Q�L3)�~�guuKKK���s{Q� �S.m"���z��m�Y�yz$��'n�sGVtC(�"O�|��~�8��0�n������'O��ѣ8y�d:�0L'�Af�䠒s�)��ڠy
�Q��h���F�Q���BL����p��I>|_�����f/��ұy��Iw�׍�qoDآhU���ұ��y�b������%:O�,���X�8�\�ԇ2��qе��rO��}��Z�ZEEy����,� ��ހ��9LOO��i�蛽^?����o~w��o ʞ[Ȍ$&��wL���x�k0@��́?�VN����γ������t��C�)�_E��c������Y��Hq
��!aJ@�A<P��"%�<���\u�-����;�ǎG��D�^G����zsp�$	�Z��͝��o�����K�@���KS�Ea��n��0SJ8��[`�ϝ�i��@Z/)}!�d�<�O[Y`���#Ҫ��U��y=��V��'N���=�P@����F������;N1�qq�J�;�p*�(�2w���DK?I�E�Ǖ%�/S��Uy;����q��q����s��^��y��X�HM�9},�OJO>�RA��G�>��wZ��ȑ#��{p��w�g�ױ#I��@I�0)fёc��y��9��5�r�͛�@g��S�:���)!Y_y�c���ʫ�5kCKt��e?���1��@
����4�0��t^L��?��?�~�a�u�]�'	�Y�� 1�{�ї��3ZO�����P��'%�^�crr2���\\��[o�i�
-���X�7��[H��|�_���)NTɔIo�0XY��}� �ˠso��g?����;���%Z�P88�v{����s��I"�}���_�!H�e�3��n#�}�3�YZ%)Lx��Vo�2�K�,����h�6||�5�󰹹���%���9u���1���+����t�mm����v��(�r+ѧ�;w
sG�Xu
۶i��Ǯ�;�M� \����v���8t�{�1�q����a�Z�X� ��@�RL���Q�T���i�M^,��*�W�ɓ'O�GI)q�v��9�y6�G�Y��FK���j�fccc���FV[��k��	I˭�0�1���[�RPz �OL$��Pn���[���6~9��,`@����4�E�y���$1=�L��}Ra�sJ�b��ġC�p�]w�k�wxu����S���X�R�ߒ"��I�����{Q`?yY����wc8�ɥX���O|��E��wb�81�7X LK�@r3�����R�'?����Eg�}�>
�l6��`h��8�q'R:�w�`�}��!�-)�%����tP�ݷ܂��:�ͅ��{�c�3��>�*���%��s�yY�'_���X�*dy�6s���c�����F��I�Q��O��g#��w:�
,}�;��_�U����y�S��sW�1���&��%z�?.�M�MY\8P�y������Cᡇ���r:�(�d�`i:�Jf	瀞hDd���N��{�K F�I��c��W�l)�'%��ƩS���c����㩗��G'IP�x�2��z�Y���&Z�����\X�<])�S)��	�@���S���~�xy�Q���\4}�0xΙ���FH�}��½�6��'��<st�q���s�y �>����ӳ��i�8v�]�<y>� ��o��g�Ť�**�9��׮�4���)`�8�K���/QÈ�3;;�/~������r!R�?Y�7���H��<߿�N��'V� ��'ZyzH�=����`��8���~��?���nNY�)6��ϳ���
{6n��]$�5�+�����T���j�֝wbsc?��w���o6G0�R��4�&�o(�y(���5�ʕ3���'�������{��?���\)xs���L�iJS
��vnm����<|_��_�O���R�Re�%5��NZ��E[Ν��%I� h����ӽ�ofHyj������ɓ'����{��ѣG�!�u������HS&r@�	���k�[9�<�\�|\|Lr�9m^L�$խ�lbmm
�����]�n=�G��AJۼ.���yj�ҭ��(3�bk��H�@V�/y�FQ�>�A���2�@�f��c��>�r~��Iz��<{�x�3N+�Ty�/7flll�رc8t������v����!~��Ղ�i;P���·���g��/Q~~�5��G��jt�R~��O
@)���K���NF�8I�A\0��{�?)��p�R�'��?�C��κ�^�ccc#]��έ�ܪ���=�"_���K N3FT|?U�MDa��Ɔ
�
Ac�:/_P�Eer�˗(�i�}Y֓��9퀾Ӽ�uukk���8~�8������{���^/]�3�u _�*	C�YE�l��dl���Hk/�#/'��k�����J/�P�_���[�i���j�dMA�+++8t���^�<y2�T�"LF&���WK2N<�;PT&���Yo�y�����b՗���$p�~�p�ϘD�����T�H�4��7�R.-��[˰EQ��� ����AiI��j$	�$�>FIFۊ����5@qL�C���B�X���^�7�W�e��)�I�?I�vq�9���Lz0"1>�_��h����TV�_
��ǩn�,���C�V+�>���E�!@�Le�h��bf�y�/=�P�����A0�����8����L?���a��t�u�i"��PB��s�'��'#����S���ξw��B_���^z套^�#���p`#)�$x��šR�A��E�^�a��g�t��$�C�܃�S���={r@Bp��������i���Q�xPy^�f�P�T7�!�\����N�~�#<��x�G����j������^�q�1��k�X!�Ľ^:w�������=x�>d�Pxf͒K�1���ks'iR�^�*������:�Zt�k��h6�y��>�x �n���ំ!I�	d��W��}�mJ:�+=���[�%=B��k���mɹ��Ҟ���`kk+W�� H���(�n)����V��D��9��&VWW�l6�y�dR� IDAT$_Qۆx��-���k�ϔ]��a�:2I
� W`�r���\%^��2I��"0�G�5Q�����} �֒���&��J�lyQ�|�Y�#	�M��=.ۡ���c�	�kgkkQ6�Ɍ+_C����&���Q��󅽈�?66���W����n�>2�i)��@J�!�3�݁N��w�'#�S�<^�J7��d	� �`�S�����y���F�����<K���(�����Y%<ˏ��'!+��/�8�@�
�
�t�����|�>���A�_j�2M����@�M��T�up���ř�I���,K�^[[[X[[É'p��a���?�Ak��C�����}���I�Z��*�py��~I�����E#���/��\�`zzhޤ"�9��.U���+�2�)Y���	8pj�d}l�Z�*�G��C=�f�Y���r��WDƒ�H�=I��I!���N'��s�G��>ͥ\���K�FdLV�qO�.������nQf��X{�^�n��2��� {�-�Tfss3W�RP���?0��-��A��8�]��WI��(�サ�[�y.

?u�T�(\�yi&�Li&��)�4��"ۇ$����8]	��ί�^����M���N��gJ�����9h�L-�ג�?�4�ZY��g#п�������������0D5S��z������5/���9��^�\Z�wff333�n߾ˠ{Ɂ�՟��m�������8ٶ��&d	JP��=����H�2����s��V���Q$Z@�_����t�r�.�CKR׸��ӓ\�Q� Qi4��t�}I�����=z8Q�"_�jbb"�Z�����R*�Z-/����/����t���RI����VVVp��qlll� ���b��Ǜ��0�X��6��P:AiE�;��z=D�N�pz���� ��C7[+@
忞�����X�f�Q�+�����4��l4�9��ʲ@�y���������T�x���c&1ǘ0	��Z�a��L�S)&#��GŅ�$xҸ��"o�6��C"������5�l�uu��	��G?���f
��1)�>�NQ���.��ױ�������Bk�f��v����G}ǏP��.�b
MN2�|[�l>7��\�
C��u=�$�W�^^^�c�Bq������Çcii	�7�`@�1���
m,&�O����gY΢(���&����������~��>�%���H�8�G��ƕ��
HR��>666��c��ĉ�v��ʿQ��y@�w�v�pҤ�Q?��S~&''� ���9|����e�{7R����]뀿�'$Np��d	"�J��w���p	�EM�~�s����sϽvll�F�f�Z
�v;I_����{�ʬh��MV@	�5E!���
D�
Q��,ۨVq��a4[���K�1�2Anݹ�9LMM�V�
�2�@��+A��B�VY��f+++X^^V#pE��!^��㧢�8F=�����eI�+�"Ğ�Z.=/�����|��cG�`��Illl�^Ԟ�^�czz:_\��h����s�QcL C*̮����ɓ�u'琯�����!.
C��1&��H�?e��"�&�a��G�j!n6ǏǡC�p��a�8q�`��Y䜘���^��h�Z2>�,�9[ZZ����=lnn�7�P�}�a�z�67g�b�������Gy�N��i@t��,��i!�\��4&E?�!�܂K��:�Ǹ����$�Z;vG���C����HSL���}�Q<��#鵖Y���R	ȟM��Z�O������y8#��ayyG��S�6���H@F�2�/��/�A?�7�X����v��H
�<��c������͡��/�����
r�ӊ���㘘��-����ؿ��0[�w������]�F4�����I�8yB��ѻ�g	��x�eͯ���>��>�웈B��"s�A`H	0Ag�b��<�(qd���%W*��w��I?�T��T�%v�����(=�y3�Ui���I+������"�8J��ג�$�3�p��0y��Q��zQ������ �T0�=��}D�[��1/�������}?��s��v�N��Q�P��<��}a���K4�X�@R��'^;�Z76������>������ĉ'
`��o6JŨs�D�LR�xP.����1����8�ƩS������|���C�aee���A4����~��j���0P�9�����jh����3Q�fH�� �<;rǾ�M�w�}��7��#G�`cc#W��kC����lT�^I���@�V����L����0�8|q����m�G=�0Nu:���{�o}G��=�\��6)�&��,F�~y�����=� �P��S��c�&��"�������'�&��������<<xR����w�
+����q֦S�<aq
��'E����$}��,����+���8p�����_����ߏF��Z������o�9�_�^�[R�"�[�
kd�!��yI�X�E�|���!<�L��͑�eV�����
m�0_���U�T&�o$�D��ϓAF�d߃8.��$�?Y&9�OP*`Jy����>�l>z���xe����@�\�Q���e�l�}�*|9�?+Js�S�p/Ii<��֒��<�e��K��C$��V����k_����q�}�ass3��*�R���h��b�xc<�PC��.�(���c8�������{/<����:�Dž��$J���� ���Y4A]�Р�G�n��أ��$����Ʒ��m�j���HƋ����KLB��0�K޿�.�ϭ�^vn�e+�����������c��}
Ǐ��_o۽֤<�c51]��}˯C>ߒ��c��p�xxŸJ�h4
�=gff�3��Ǯ�f̋z]�b^N�!#Z������'K������d�`����q���\���R�Eg�u־��lll�T�fh��g�������K��̥�x��ay^�V�E��h �"���q�h����e�y� ���k7kn)�c��Y�N,�Uڞ}��7w�(�\k�
�0|���~:/^f�i�ha���{^�dm��N�����=1�_��B

?F�G�9�9�`�ۯd��e�i��
͕'>�ԏH��jq ���j�T*��Q�V���!���ų�1�m�:�")p�!����OW2H�Is�QsjH� c�+�*�*�zQ����RA+��E��BM!��؆8�K��C$O��a/��Gj:��-ƥq�����T*@ ���j�Az������~Q��I��G�W��>t��\C���)@ZP9�^���T*��^���VC�RA?�K����z�S�8΍!�Z�ޓ!o+��˲�~��Fy�%��W\��1����yYh��G��#�i
��:F���j5LLL�Z���[n��U��b2��}��'������<�'O�dJ�]�s��L	R�-{���ҽ��X__G���yҝN�@� ��/��e���Z�����`)��"Z=/�h��[�d�	����m��M+&�P��Avl�
����}����mh�����gc�� �	+����拥�PAo�6_&N�	��gsTa���('T��	R�dМ��?�e��@Y=]�G/I�K�Q�>�oe}I2�C�����P��w��P�t$(%��%	�,�t�٘�A�S���������1�٘C�Yp>��Q�(jD��ć�����d̮�)n�J%�zY��@��(�Ѝ�ԃ���ȁ(�\�
c��&�H\L��l���
B߇Gכ�#�}���8F/�s�+J\}	�m� -8�pY�
c��W96����B���>d��9&e�<r�y`S��糠h�DY��j���OMM�/y	���Ԅ�{�c�޳�⊾<ˏ��;yJ�)N�R����g
�7�}Lހ+�?���(k�����������/��
b?�
��t ��k\Q	�9X�|��$���m��r�΁>0x�U�v����<�� Ez�&�.�ci��c8�+H��N+^7�m�6 ��o����= |^Ia���������Se��y^�Y��3�$��CR������3�!W�I�)A�?�X�J�G��#�G?S
�$A?I�Ӈ4n`����C>����$9
����ྎ�Ԋ ʨ�t�"�8F��������:g��\���DZ���A�6�|<��{3��{Ȯ7��8���IњO�Y�
�+ۦm��`�g�R�m���+���@!P�s�)Y�����}7�O*U�eH��+(��C�fq���S'Np�S8%(��>�}f�z�a��>�����RN	�<��y��(�t��E� ��Ⱦ(�V	���f0&�i/0�M��98���_|\UQ�MI�mqo���y�e勚K�OMQ��@*MR�\p���������3���('���~�2�d�I �q*���Pݢ���y��5X�!k-�I���}�hL����@��5cNDݼ�|��M`�~�k$��9 Z���{��/�������h3��,�[��j᧲�� �D�#�+����OѮ
���/������J�e9����-�Z���[�|]Z԰^��{���`nv_��`���;1��ן��a`�p���S.Np�A�"��c�糏 W�s�9׬���+�nll���`eeE=�?e��U�:�-�$&�T���}�'��'���c�mj�]Ge5��4>�� 琗�j9F�8p���p��A�d�o:���*�M�O�P�y$8��
�
�������~~~�q�T	0�bzJ���(�,�=�2� �h���������y�kK�&z�ɒ.�-�r��Ɏ�T���/a��y�c���3ͱv�1������ϕ���J(γ�����5yWL
D��C
'W^�~�}$�嵾����~�J�Z
�j���ln�߿���R������W��b���'O�8���&,8Xz�)q
��4��7�Ӗ*/��_��Ϭ��(A�k��*���5`V��f��/fiu�`�2 �����I�ՔO�o
������-��8���D�5%��W̎'+���&`�ya���}�}�1�	tҹUٓJ��O�.�s�)&&��X^��4;0�P�up��K��^Xy~��T���2*�s�M��8���� ��iL�=�?>���t�����S��sED��9Ȗ��hVs���65E�d��"���	y���$��S	�ӂ��»L�9;;��^�f�e7��zm ���dž�����U���%6 � vp)%hi� [��%�~�7����a}}���h��h�ZX[[Sx��--���b�hq�&����x޾�]�o�PL��e�7�C{(Hr��PZ�m��iee5��L�*S8ӼD�1h}2͓��h��ߣ�cSh;)J�:��Q�[�%+vti���=d��gI;^�t%��\Y�죦`��<"JY�ٌ��>��'���s�L*@�j�v�V^�����+T�T�짦\г��Q��p��^�����D�������^��W���\s)���{0��C���o����gP����DI2Ƒ��,A�U]v��^G
@���W�+���@�v��n&/`Ʀ�M��d���0)���yY���wپT0L �g�I4eC���\�2&�,+�����){�}�M����{;���s��	8j�G�^)�
0����~�i��c�J�	�ju�2���m�屶z���{.�9�m&˺V��ܘ"[=�2�[ݲen��ez�z��S~hEߙ���@ߋ0��V�唟������8yƅ)DU�eJJt �d|�^�{�����:677�e�i�{���T̙,ؚu�kiU��6@�A�
�PV�2��(���X���;5Gk��5���	x�����_SM���D��r��旗ю�)��v��6��,��V�	�K`&ۑmp��<VZ�M��
�ڬɦ4���
\˱I��MI2͵�L�v���9�����S�e�6]�y�ʔv����i~x=�r�O{�g||ccc������4^��c��7������*��=9�ϧ�'Ϥ8��3.b�0N	��U'�y�|�P���sεX__����Pl�\�2I�38�/�2Щ)Z�A�6�o��,�&`�N[S?m}��q%����)@q��()\���-�&W�d�j��~�4>��ش��5�/�2ͯ	�r�>�	��,���&��N5��Ų��Щ5�l��,#�g�z�RFk������)�1���K��%Tʙ��c�(-Ŧ��P���sllSSSy����|�s����JSp	�W�%��+�:ڏ�g\���ea����.t�t���+�r��\�t��~�@	�s�BZ$&����tP�]�{x.Ǽ��]�n��G�&>?�:�~����M٢�6o�( ���o��?>�eJ���]/KY;Z���g�u�me�J
��v�eW��em�Sc�O�[m���.����Km
���� ��w~H����F2є����r||~�ʘ�\jex]r��̙�-m_೙՟S~dzO��s����0/����꿆�bzO���v�'����`��Vk(��7��x�e�s�u�p�
�+sE�,��.��,�lG��_eÔ���2�˿�S?5���>���_��f�d�g�y���<hVz>NM��k1	�@j�X	�mJ�vP]�r���(�m�r0���E,�6)�-���O
��}T
�(
�	DS=R��0�p�o�rQ�e��rm�l�ϰ]e��G��O3���~����j���Dn񟝝����mV�ːZ���O����ɳ@����"@��.�<s��b{�Yg��)ZExsss�ă��������H`9
��������e��Q,�6����4��2��m�ao��2�٤��,������d��x�v-�v���A�7��G����P~��H�m���o�&`Hc��oٶ�M98��&�ؔS�����,��~���5c�ʨ^6�E����U2)�ڹ�Ô��/O�9??��^��^c`����-������NNKq
���VJ(Ar�Y�^��a���+���;?��t��^�~_UF��ox��|`P�k
�f��겁O���T�fA.�S=ڱ��i��[����(k�����BU�f�׶�������ʶ4�	�#�s�;�o
��F#����d;4i�W������5�]���M�ܦHh��<	���e��%�K��%�����z�9~�Ș�2E���!���)�g����{����g���_s�-З��y�)�'���������89�EQ�Hq� Lt ��h��������&��T���[z������5`��a��P|L�o�O�U�8��e
�(���gY�?~���ڗ���e�Ҥ�؀�ַQ�7[e��R~��%�3񳵶L���Qi��~�_Z���2i٤P�Z��]ƶ�l�߮)����_� ��/�x��*�!�Nۂm�yR��޳V�abb"��Њ���r˕��.c@�!�)��f�r+�:yֈS�<+DP�h��,A�.�2Q�Pc���v��w��G�t�����v�E I�\x����
 ��6�rp�������}ގ�Z��D�;�2ۉź��A�[L��fYE��0��Q<�^S�-Y'�Ө%&�
��̩-S
��#`R L��ܦ@ȾK�!F?VS�8�-��2n�
���QhN&*����wm>L���z��n�}�I���s�?66���qLOOcjj
/}ыpӧ?��@�+0��#��m���S~�w��8yV���p��)]��Wj<��^]]���:����t��^�^q҅����m07���J���A���~�z�_��BM����TT��[K�i�́-�χ'�����S��pE�σ�D�, IDAT��)Z�r�"`R4eI��ʖykd;�y�%�Jm�y�L'��PܺkSD �h�x	,9���K્��N>&��u�th�L9��)�A�>j���H��}��+e�@�t�<�zd<�MQ܋ן}9׿�h�����%�z]`%����>���g�8�ɳN���4�b� �
��R����K�t���Z�.�b��~�Pl�Ei�j�	�l��f�2|�εr���nd��k��>�vM���&�0�Q�T����Ψ�'��r���j}e�`);��|����R�%=�>ˀ��5�(}i�M�ڤ�p���+�e|����W�'P��h���qj���Mʉ����kfԠs�gR4b��)?��'������������N���Hy��Hy�D��)>]���g�8�ɳVE��T�@@
yLV�+�=��kVWW����f�����%�@� ��
��ӡ���ϼ��p�l ޔ�uTн4����Q��Q��o�XU��v4EP���?�0��y8p}� &`Q�=�X�`#��e�>�2
�m��'.��
�_B��UN�P�=����W���j�V�������x��nn���Y�)�w�忉���A
�)����;yV��w;qbL����1XAx
i<}�Y�|�Yg��iI	�� ��C������E>��{:�b��G$��3%�����^�o�����Q2���N
��
��$�lǩ܍�u������e$7^��������NNW!j�����|E_��LOOcvv�%a,���V��#��;ʏ��8�ɳ^E�҅�!�
�Fqa[��e���+���C
� �aaaM	0)NN_�|�_��Lʁ)��t�	����ϯAW4x[6zP,��c4�FVL����$c��Ԏ���8�e�t�ٖ>:9���}��S~(�Q~&''1;;�מy&��ݻ������� ���
���=���<G�)N�3�(A�*-6�A�PRf`��p���_����g	"O@��JJʀ������'$���O��H���j���́ap��26��h���NW�����e�|�a��"��m-��~a��-�@�MߵW�����VE�׷���3-�����T��Z��"�I��E��#��o"���}s��)N��'�9�_A������{.���?8rD
&J���'��|!�o�%�����i���]���?�/e�d�~�h�'MY��v/��Xw�;��m ��,�)n�bdP����?��/?���h����	�������/p����b`�_� �gE��_F�;y.�S�<�İ�p��)]()30����/�����M��m���<&�V�ﴽ��<N	8=�Vl���Wе�3��|ʼ��~����S�Q�L[f�2��<���[����2ؤd��m�o�w`��NO1-�EY}��jn���j�ʾ��ק>����Z����݃��M�	�@�������y�G�q��8yΊA�҅�g�}�����[��އ��&�Q�@��B��B�y@���`ck������R$���3\	�bZ+��XxkI?�Q�רDR�рL�
?l�Ư�
�Mt%@��e��r�k�m� �O�����>&
LML�����E����s��h401>���څ�V�_���㖪߅�՟V��BJ���'�q
��紈��(SQ��1��g��%վ����}6�8������Z-��k�{�����r+�^��_��k��� _������o�k}�J��I��L���i��]�������h}м<ؖeHn'qJ��'�����8?Z^F�V����KQ��D����m�H��@
�劾����y'&��'�	��I���?F
�C�>���"�}�R�Y�����8:�<z�I���BL�q���t�	8�e]��
��:�a-�f��\���ʑH ��V�SpI��M~�W�6͢�ǥ���,��F�2�����:v,�������;����X�)�g�s_��뀿��8���B<�K2+<=�	�$'��/#�.���7���8~����0eN;���-e�Om��k�ؚ�C6�[�&�@�ا��A���spxy\��!oW$5�k(���e�!�tQ[�~��!���g�b|��`y�~:yzD>;{a�׼�5,,,�;�({0X�k#�N�=5ʏ�N�7�'��{�$9�)����H�B���R\0�}l.�� ��2V89=��}|�-T%0P��ۂ���Y�e�6i��_R{d;T��ؕ��$��i�-9>̷kM3��X�c�yaL�J���D��N���F�Nw�#p�T�\�b^@��/�2	�s��s߭���y+�8y^��
��)6����(/d�?��|�|��!=z�f�zY{O˸��E����2�z ɽ��e��%`�V���G��o�U0�b��P�I��
�Y�$?���M�C����J�����`����iJ�V/���P�
�]\\���"~��3q�MCK�|��^����a���D��X�;y>���r��9/��%����bZH_���p��쳂A�8.���l"�|m�`'Ϭ������Y����n`�>2Y�I���)��(�fS�{�M-�
�G����(���u���mJ%Z&IҠ�V����b2h޵2�>^���U)��ZT1��ܠ�l�a�A�L^p
��c<��1P�Hi?!���؁'�Wq
���P�0�#D��� U61��nd��/QMH�_.�hԟ�q8]��m�n)���Fۯ���ے���Zp���H^���p�ե�%��c�!�T2���2(���&���
��@�g����YJk��"�����O���|׳�d��A?���'�[q1N���2q��a��c)%HJhZ�]ي�&J��>��m���h!�x��ʎiI�ǙR\r�f�.pZ���p@'�3eY'�2��reBK>FZ
����6>�e"������_�<�Ϩ��{oZPL�x�`���l?��ůk-P�����m�c�d�4���M�Ҿ�-�&�������i��K��Q�F��K�;]|��
J�E�)>�1�����;q���8q�	{1�;����H�\!�T�U�'���z����<+!�`�o�~'^0��+l)A�	0�0�f�B��"}8�C��P�H�,�Ǡ��B�Y�M\~�W�<h����Q�����9�$�����d��By��2�6�/e^
�������R�(P�q�~�5�m��Y�8i"Ǩ��LL�
���t�Ra��ͣ�)VZ�T����ÕW�~]��<����K���H�>�~i����'q
�'L��a�ttO�s�5�J=[��Z��/+���$��}�/?i��nN��@�i���l����80��6M$��2Y��T�r҂�兗���	XF���y����`�#���r����V>O���6
�)��V_�p�mShFU$�7�7�a�V�<��JET��:O۵s��I�g�o�U�Afz�٫��}(�Aޞ���1t+�x*{��!���An`�� �?�Fbz�É'�8����؀>����t�(��3_�RLMMajj
����j�T*�}�2/�ɪ�m<I�l�V�^{�K�l�d��f-���7����h�X>��<��."� ���MJC�
��Uf�7�f�m�~X~��KO�I	4m��\a�����6�Y�~hʫ</��b�w��Y�th
�T@��J}�uk/��f��c�ڱ�eS����g���)��<F(�S�l0��z��㘜����^�k��h��?Y�s��a�N�<��)N���+�Г��}���Ә������F�
���U�0�f�e
�j��o�/Y	P��4k��_�K�@�z��\�-�RQ���4�ȁ�	������(ޑ����_e�m��p@L�\�FEG�u#)j	��,߁4�M�jٗ��&ϏIl
�f����>h���n��yTd��u-�Q��!
&%@zJʮo)&Ϥ,#�:�d��V�h4�#�����4��-��ĉA��ĉ]�@12
(����1??���9LMM��h<W{^��H<a�����4����m^�`s�K1�j�
0�L���_M8����Z�\�@[ �,�r����-˱}D������@�40+i���P����zhȎ��q����%s�����m�}$��FG��5���d�2�ޕ
�	x���	���R9�����hS�?�-��S��X͈@ei���7
LNNbff�����)�R��>���~�8��S�8����p�,x�UWaǎ������,&''1666�	��yL A��}��	y,0
B`���[�MVR^^Z5����EY#i6Z_l�K	l��)��g��sTF��|�
�Gs�<Z����P^�/�E�Υ)�����X�қ�U�mJY���g�X��[�~4�;P�kʽ��ʷi�2*#-��v�mA��8��]ok��j���ll������������q�5���R�H�;��ˉ��8�����@�h#]`���?��?���"v�܉�������hJv�V��-0�"ք��<���e��ʨ����?�j:
�X�<N$Ҳ-��o�~�g
*��I��Y���<����k�}���7eu��4���������=Ш)\�ߙ��-��(�Z�;��c)�i���&�a('��y��ۢ�1y�vyI�u�͑-�ڦ|BX�9��w�܉n�>(���(z�8qb�8qR.Ħ�
@S+|���
���\�	�T �	�,$&�C,�Db�(^	�����d��,괍�gM��ڡz4:����6*�~M�1y<���G4��3�OҨ׍M�|��Kƒ�5�-���@�CY��f���m�� WV�
��U�'),|����}������ʏ�p/+�WޖW���)�r9�I;���V7/#�%m���Z$�0�vL�����\رc�M�1X�Q*N	p��"Np��"l�`btl!}��H;�k���.ٱcG�	����\�yC�c	���
�Y5K��ϔ��Q�	�x�E_�D4��/��|p��
h�x�!H/E����|���)�KݮڷQ�@�q���������_�"x��K(��o���\wgML�u�M��Q��,���,��@�����z�x��_�p�/�=jO*2|2¦QM��2Tm��q�)�n�������F��D�^G�L����8Y���I�V���IXp
�ņ�n����/�����)�pU�"T�(H|�ĞR��d=��H�����2n�ڛ��!i	��kS_��跴�S*(�5��D��r�Sf��2;��uT�RF� /�� u��Q�Dk��ˏ��x=|�i�ݰ��֖�j^�7�k��^�=EeL4)�Q=k\ٔ�30��]R�9X7yk�""r	�y���o�x��-���󿸸�;�c��_��/#�Per��8)�'�p��9/I��}Bxq@�l�Y�>�U�~���~���2VVV�l6����^��~��8��1*�
�P�d%�\<N� �[�m@I���C��0�
kK��c�e�>ɷ�c�m�2�}�
�����e~^)/�.�M����h�b,��9�z~�П�f�e����oj��k@�l����ro6�˝���~9�ˌ����q�c�����k9�P�K�璎����L>���q��_7>��v;��W*���all333�_�Fe@��a`3���-��ĉ�8�'%�V���Z��H-N�H_@K�8��*U�t�w��A��' �"|��YZ5:�&&�O�%w]�l}����K*�n�2��	�D�L�uhu�}|��C���q�m�ee��7�3�y{Z]#�1�z�h�i�\�vx?x�LVi9�e��RL�
ӹՀ�v��e^+:~ϚF����H��-��������k�j4!��A�?��9��e����+�f�Y�>��\�'N�)Np�dt�x�R�nXCJ"E�2�ؽw�q�n�&T[0����:h`�������Q�i��i}��},|��5@�h��T������o�0L��t�\�1pJ��-�ΰ����a�����oS|�M��T���_��5�,��&���y(����C�R4�m��m�?��?�ϟ-6��) Z�@�lo�$�������<_��>s7Q������ɨ�'NF�)'���N U4%�;�cώ�E�'���u�h/����rѬ�Ȏ��&$d�ր��.3ʃ���$4�L��\Z<�{�}�� ay��Q�	���Ef�r���8.�AD��м$��/����(^���t�v~�ol�[q����A9��)B�
ؓ�L
�&�=�i��LqF1��c[l _S��B�ȟk���	Vz��������'��S�8ن0%@*-��h+x.V��{���w�h׮RO�dz4�&봉"lY�����m�� �ӣ(�<������1Q��$�*�3����P�w�Ɨ�}�A��re�y�r&�?���L�\��Ї�%�e� M~f�����C}�cy9y�S��L*��RN�e�6Q�8@�ITRF^OR�0yq����������s�N�����I���
��g�w��	�S�8٦d11RbéAIXF��r����=g��e����^M�N��BIЬ�&�%i��f�'��2PX�1�0��@����h~ ��a�*�9�zߑ���ɗ�o��e�8�"b;�L~�V:Vo�5)�H͂���pV�a��hc�=���Qz��@�������#~��q�>���K�?R�(���w�>h�1����~�b���������/F�,��*
���;q��)N�<1!O����֐*��V�ۻ�����^�*��	��V�t��*��R��QA'"��`l�y�_����6��M4:��W��s�^�ͭ�m���0��v���ڸ�R����z������r��(ޡQ��nǘeF��d�/�:��gU���D�1y�Hx�~�������)��������ϡ�L�����}A�V��ZXX��^�b��m�]����7Z�.�����t���`_��8y|�'N�(فHh"}i�`�V=����=��ͩ@�P�<��>�pu�t�~��5p��,i�7!S|�(Ģ��fn-5YeM�Y#M�SJK)WlǓ�BI����?J�|�	�re��ks
�|��I��қ$�������c;��]#�Y��6�#b�h׾�U�~��2~�b{$��c�g%�֔(�Kk�DA2��tϛhP��_h���gY�I����W���M�n����&�gk�x�;������8q��M�z>v��ܹ���������&&&P��Q�V|��G3O��H� HILT�uY�~�p@!��d��}��1x�|g��U�����=�xIg�%/g��؄���X�9оۨJ����8���η�c)a��ҒJZ
�Q��r�>�%��y>F��0���7Y�5���1rW|5:�6�^z�x�+UI�Qz�L�=�I��pF�!�O�^������177���E������{���/��駍"��Q~�8y�)N�<AQ<2CP�'���o��2R���1>>^&.�G<���5	^�w`��DD6+������(8�D�}�ڨ'�!^�D�0)B��3�j�'�|qӼ���휧2@��/�)�
C����A��ter���%���
��Q��?�i����SO������i^S<	�%�L~��(S�e��D��I9�{�bo�b�a���h4r`~~;v��\}�%�*MH��:��~6T��8y��)N�<I�2=O�u��v�e/x��s�N�رsssy� ��)�hT0�,��J����}��r$�6��K��
��� )<��dޮp����� �+AR��C��K��;�%4����)��z�Vf	bmJ�I4ږ��O��yє%9�O*ң^s�u�߫&O�m�4~>?=�4��F��Z*T�"�����jh49�gqq/|��s�N�v�͇ IDAT�mW�Ai�Y��8y��)N�<��=��z뭿Jt ��@��(81��5���l�H��D��ڔ�5δ�� 9�Z_�����}�m��G�����u��C �ӗb�]�ݖ��5�}�H���ꯌ�d�k�X�r�-W9N0��D�cm;߯�CSN4*��w~?��d"eA����
m��8�:7�$҃�{��O����9��/xn�����F��Y��8ydTc�'N�!I�p�VP0	`
�<����M��]t���������u�������n#�"�a�$I�I�N�h7Q���~�>��^֭/��m�d��C����6N�_����chw�(�;1�����Ś+Ǚ������o�cH���7�	���e�E��!�:�y-F�뭾�$��\<����!�l�hL6�+�r��]�횅\�������l��
�1�6d;|����!��%�����>��*j�&''199������c~~���A��O�~֑�6���w��)�p��)�mx.ю߷o_N�)B�baf���D�Ϙ��e�H #A)�^�c4�h$e��Q)�.e��8�K�02�/���1)ge�^��K�����7��j ?��(MR��SK�J�?$�������S�*�6e��k�!ٮ��@eC�u�:m۹R[�GA�	̖��������/��;˿'O�8����HF�	8	}�`�ݻw�qǞ��E,,,`ff��A�+6�B9�b&+����0r@�Qp�H��?�L.J<G���h@��1�Q���f�}�Ϗ3):�Z.�"R4
���������?���H�� I��'0�3Iq�����^B�kc�:�%c�/��į		��u]voh�"~��}c�Hɶ�~��)�;?�|�|�m:9��)���O|P	��9���x���+�H�?�~�߉�g@����S(O�*��e<�� c�'��2%�^�&�+��Iq�@FJtp�5	X9H�A�\��o��J$��Ʃ:݁�cԇ��4}*���7h�=�������z%=��$	�Y�t���f�G�2��}6�>0����J�2ܖ�koS�h?�Q�ײW���t�H����Wy<oK�?Z �TPdl��W�~)�7q�I����/��-�p)�߉�g\\�'O�Xb&����S�*.~���~�S�������u����F���wڅ`>	�xvie���{�89����w��gߴX���M ���徐��%����`�/�-۲�
̒�� ���͋˖l��^$c @HX����$�
	Kl�
��Ś���������S�Ou����d��>��:u�Tͨ��o	q��;Y��1�ȲB�O�y�u�G�ϥ��Ώ��F�����}q_��)��xC�����?����������@?
J'�+Z��zQ��a�_�oU�V�h\i�� �8�Q�U�g��\��W�����~�1�3�q��\~_�������y|�}����z�5�2b�GGG�x�b,Y��v���@��
�/G����p�^�����7�ڵ��%K�t�TkU|i��|��зB�.��'�������5'�ɠyB�q�>u`?��{+���^+���������p�g	�݈�����������
�e)k<�;D7w�;6�P�J��s�y�߷�1?�ȟ#+�&�����������?+ć�����b���k׮���/@�=��O,��p�@�����"����7�޽��n9J)�Y�=�ы����sC�ɜ�u�[D�0��$^�ެPn5�!t����b����|�:C
���[��yBނn��SN�o.�GS������n��]�w_��닽�W �:_I�:�s:҂����Nи,���|�U=+�6���Ǖ�n���A��f)H@�>���h���S�5�ڵk����c�؋D�A8ʈ ��	 ���x
�B�ἀ�<�d�����|?�C^.XkoH�����M�wͯ�_���bo�z����/du���ڟݑx���L�������L�����gK�'����CV2-?�)D����W�8��.��
%�����;���"pOB/Ϛ���i��C����.���.i|���$`
b����(���<TPD�|�a7�޽���˖u���a&��3"C��!����ڭ�Y���������k�cY�x�o�֤�/���"+���|�������˺/ZMA>Z#�&�yT��B�����\/BXQ
%v��uJ��C~n/%U�Z|�z����I�~>O�&z	Y�ś����۾Ns�5����C�P��	�],�7����/~�CA8
0%���h�00��[���\���'�����	��pŀ�g�QgY���ݻ�.�x8Q�v�0ˋo_�5�Ri�݄��P ���kw����N|�kh�+��zb
��;/-$�9��[�t
��J\=^������۟O"��C?�C	���C�)���g#��1�f|Y~�������˖u��S���?S�g��A
���p�@��?>�y�0aA�H�=��p��^���uׅ��������bhh}}}(
�b��Bl��e�o��1.��1ݾL�u;$\sOD7�)	td���A�ym���#�ݫ�����?���"���ʏ���]�52<lb��X!if�8��zb��fvg`h4�nm\)�۞���R�ݔ�^���j���6��g�>v��e]�
���}�F�w߿�,OL�&R
Z)��	��|�M�_�x1�u�I���wa��H��<ѷfo�J=�_�RT�l�P�iv�)��������/����^�~������駟���fff�h4�h4�1b�ҭ�S��B6_��������˴�c�=���B&/��M���}��3�#YK+@YO
�Yi�*���[`�}��ݐ�g�K��c~�;qj�U	Y(���|��000���LLL`||������[n��a?���O�X��̧X��A<�p��P�q�Oxz�K���n���^�ۿ��K�b���waA����#���۶\.�†��!�7���W��$��5�j�g�d�����&�k$�YF4����Ο%��{	��a(�f[~?ƫ,	��x�6�=P(\m���

add���X�x1�.]�������[�1��|H<�<޿�`7/BG�xA8���`)µ�ןu�Y�'''q��A��e���6O���{m��i��
t�~��sB^�P���������'��7���z��K����dy���7���4�=�k�N~� �R�rϕ|�OF�����a||��o�>|��1p���c�˿ �� �L	��Ȁ�v0�,AX	�tժU[���P*�033�Z��j��V��V�E�p����f��f��8��j�D	�u�������[)T��-4�K��ktl����2�3g�y~�w�}����s:���P?Ï���o���~��|���CCC���8���p�w^`[�r�T.{ھ�`��uOf �_�-D�c�#�\�nݺO�E�ET*T*'�s����q;OA�^G�^O)t�G�h�zm�����f�͊Ͻ!�>�t�s�����w��{���h.�wz~�^���S/���^�g�0q��*:�ԙ���������N�3���~�o��wEb�o������,���� �"������###���8v��y�O.}�*?b���Q��O)�2|pٟ��m��)̔�κ�[���_�VQ��\�}n6�h�ZP�����X}ku7�6}	�@ZPκN�����ڝ�e�Hǫ�$�}!>d�y:�������s’p���d'aOQ�(f�׹$Y؞�����k�G������}�����?�4�_�����`
�6��& �����	��)5!U�W���ҡܑ���y�q�(���?44���A

axx�)�����'�#���e6��`,����_�#D�c�O�Ҟ�%vv�������o��:E�,�$��x���۪	i�Q���W��@�b�;	���/�g)~5�P}�:A�w.�g����y�ج^YJF�[@��z�����Mΰ/FpMD�ȭn\��!�;���3|%�������c���g%<wR"�����+|ΐ��M�GƘN�O��!%��#t~�=���kκ?00���~���a��FFG166�b�I�'�(7�x	�wL�O ���)��~��/�	��1N�'`�0`��>3�;������OczzSSS�V���5>�uO�x��#U$��J�/�~�ͬ���<I���9���zݮ���>W�?�+NĽ��cΈbD����\�QD���b�iD��筻?��v�.<d_����@!!��r�������d��Þ����@�s���C��?7����ZgJ�P
�@�C1������ŋ�SN�mwމ9������@,��p�!
� dx��6`۶��.8���w8p��(�������|!�sH�Ϊ�%,w��sa-򎅔�N
��Nu���ns��ɡ(|m�X�z�!�HC��U���J�I��:�
��j{Vv���{/�~u��Bm(�&
�		�~����)�'�ܬ0"�>B��;7�V^zo��О�K1�T�gٲeX�ln��V!��t󥐟�ݪ0M���/�!�� �^��&��������v,]����Ã������K)DC������MH��#-��z�r�����K $�w��}�:Z�6?���:	�Y�t^/���~��бZT�?��h
h�Xk�CC�E���s���C���]���h��h��}������H�J?���b��u��D(D�������������n>c�۽�����l���������[�Ƒq�w�SH�~f`��X����@<�p�<
���	@�@� ���z��%/}�&�¥��x�%������$&''1;;��W@k�
ΪpÏ��!+8��y�B��2��?����e���� t���-��e�΃>�.lK!	ײ�~[(5���ͫ]�V�v��{Y�U<�}Yѳ�!p<+��G� Kd5_�%�?4.4?�Dc;%Ӿ^�W�z�Tէ�����(�,Y�g�tn���+|:p�,6�����V0�$ɗ>��5��_�D����`�>e���o�>6��<�?`�{�K]u�y�}��R��R��*+�+g��o�U���BBv������F7��:C�\������Ó���''�+�����/�M7�ʴw!d����zP(��Ɋ�	ľ���e	�Y9��������E9	�ӟ�WbB?
��ۘ�Oe>)�b����1>>�E���n����)�c��N�
�J�i���$�A�n"��q�(�p��)9���>����H�Q�]�q���:묛���055����J%�j5�j�TyQ�>�N�d�����{�1|���o_�ut� �i�PC��ܫr�uo�(>�`:N�ӷ�7.���=�(<���Z���'�u�ϑ�]��C���� �<���<
W�r��|�5좘�ŋ����M�[���vK~#c������p�!
� �XHdR��^��� `��b�a���[���1==�b��ʆ�j5���T� �5>�u�	��X��N�:��t:�p=~�P�B
Jȳ�'��Л��������u��~�1�5�|�Mۤ_���f��~��^�uM��t��^��
VV�͡(��x?	�+�B������ʗ��P����K�<)�gbb��;�:��%0���0��,���x���&;�%��_�SD����JA�kh#�+���.w�g�y���SfggQ�T�r R
���`|{V�@���<�����ߋ���[���u�=)<��Ie��Z[���e�ۜ���_��P(��ۍ��–x?�����^��Y�;)|NH������Ok�J�{���������:�NLL`ѢE����C����T�Fұ��t(��i�=mb���Q���Ы�E�{�Pu�mk��.Y�j�6
	����˅�"�)�
�VА���!�C�����Z[��R��G����{^���w�ÄSc�w�W'��+�4������r�Rp�Z
P�EZ�xywՄ������I�����C��s/�E|}!���{(��U��?�r�O�?u�ξcccË��||���/D�����j�U�%��E��{_�wB?D��g��3���\	��$
S(�����%�?�3n���t�~H��)/$����s%��\�P"o���������Y��$�����{���w��S����]l�
�Q&�'"�ކ��$�G%�J3�6�+_ыz<�l!�Y���P��/��ϲ��1���>�1��(p�[��?7{y������T�ϗ���5Ɛ���B$
�(����J�����1��/�<D�g8�"����a� 4
#TP��1d{�_�a���x�a�ELOO�R�`vv�z�F�M�6��0��hBC�?�o���5�r�<��0&�~�`~�N�A@o��o��.��Ϯ���C�~c�7c���[]�9o�=�A��+_�]M��^��m9�g�dz�]�W :����		��.�������122�j�?��Sp�����a�iW����VCR��,�����/�t��wAx�����+�H�i")�WF��s�ݞ��E�o�Ԗ-��/_�����axx�RIE������5ԭ�/���66��!!��Y�������������4�4�Ĉ5@]�4L�/

h��K�T�o�#�i��q��:���p�uv�Ȋ�ҊW�y�ϗ��z�fV�~Vh�BRV6���s���+�Y��p�=/^�N8˖-��۷_�l��}H���C�y��l������Ș[�g��_b��b��4�$7�o�3�[��v���G1==�����̠V��Z��r�<7����Bq�e �IX���,�B�ڡk��GV~�����U~n���o~�[fN��1B>���d8�CC9a�1"�V
Ql����5.;5y^��Wu]�w�nE�t�����.�wJ2���J�?/n��M����J=|�|_H��9���?::��|2���q���.���P�����A�=N����/1�@�
��%���0�'a,��<��Y��ᦛ6._�'�p/^����7 ��9+�Rʅ=aknHX�c��BZ��5ڭ�~�%n���Ȋ������\�I�|�
B/��_�[,!�l�vFm��ĪO�{�o�X#V�3�c����\�z��S�������+_!���ԁ��N����<�y�[#;٘���ne)��ϟ�w���'�?�ϧ��ccc��b�
lݱ�2d��a���e��H�~��W@�,�nU�g8�@�@2
5�܀1�Q��[;Lw�����x���Q*�P,���7 TI�[p/����P?�$g�(
��c���dz��~���7��JZU�6�Vʓbw��m���f^�3����t��	���w_5�t�ӧK����+�sC�e���:7B8����B��sN:	7�z�:;�K����?��X��E�AAR�&L!A�,�[VH�ek֬�<55���IW.�R�d�ݒQ)��ƾ M�{	���M��!:�$�P\8�~���}�������O�6�>1�I�td]����I(���TiQ?l�Pv�N�W��1���d����t]�w�L��
��7�?$���߭��;Y�A����y�����P]���a�?>>�E����o����#�S��L�o���:�J�� )D!��S���<L^@?L�0�L��S�[w�9;��=�lc����8}¯���w:�W�y�� IDAT�v>
U!�$�#��_۩�>4ut���`enp5ǔL�X?U챣X�_sܮŝo.���U��|^�H�����w����P�}�x��@�+ !��!	:������!��Ň����;����D_���6�$�Wb�A�(� 	(y$��`x߀N	�׬Ysu���F�\F�\F�^�
�J@H�Ϫ���„B���Ca>!��br�
��ѝ��L}�ě#�]g>����>�i:�dn��^������T�����"䏣�����@Ы�)��p�z��h�"LLL���o��!���!?u�Ű�=E�!QA�	�!		�C�A�+��l����g���
	�%7�F�@XV����1����!���c��~���Q�E�_4>��ァ���_�p��NC�Z�:���-Ԇ��B:u������[�rz�O�
/�c��\�WJ�?�||w�}�:t�!��?
S�s&ܧ�t�OH�� و BOx�@�"0l7
�.�Y�ˇ�p��d���c��|l�� ˃��)\��R>z���%�&ɻ<g�����,(xb���<%l:���.�����y�~uo^ ,H�\@R�)
��C�{I�
�K��?t�?F��1L�]
���W~����D����!��S�?U�ႿӕD�����,$�d�<��=�$7`��;;L���I!A~n)Zk��кM8���@�����z����Co�}��!�xL��0p,�7��v�$nP�&��� ?@(�������S:#��7<�����p�&��v��o��ݒ|��{��O8�]VU��8}�������O)\�ˡ�j��z����P(`ppCCC���&&&p�=��C�# �)ɷ�O���������pHd(y$�BG�F���s����r�8F�բk�ߍ-���o|�s������W�&�R��I�������ߏ����h�",Z�w�q�[2��c����/�� ����m+‚�u�JA���!$}z�
8��3wLOO�X,�X,bvv�J�F�-$�x��������|�����5���K������C迂�0��d����+�5âW�O
��������������p[��֡s��#�r�|�
�p̑�nn��իWo���L��j��*A�!�'7s� �|.����W�hz�&�1A;��?��ϥ���43�h������b�jw=e��Vd�h���y*�-��o��)l�xUhݔ�;88������cll��/�Ǯ�~=��SH�� ����*�1�<����7���b����iT�UT*�Z-�Z���cZ#y.�ͦ�ߣ�u?���0ǭ����t�@�MA%|m0��J���L%d�����������CexyL�������/
(
��?66���5�7l[����ӐXA?oM� ADkM�I��Y�`Ȋ9k_� ;7��]�v]��M����#��\.cvv�f�F�R��N觜�>&�o<�̲@i��2	�d�wez �V�MV��1��*R�Y�cĈ���ޔpOB|b�'��1r:T��4Y�5~�y/���m�ƅ{���*9$@���*<鷿�ߕ�|��'��m�.�S/��I��XA�c��U��9�
شnݺ�ǘ��NU:��V��O�?%7S߃F��z���r���׿�(���*�(B���q��Q�3�L��E���Ĝ�����8�r�#ث�YD�>���.g��p�����SO
>�\.�\.����|pp����#@�j��B�
C���[2�z���w���8I������`� œs��Ex��2�{�P�Z�~��cI�~�N9$�S����i�gf0[��V�9E���W�j�����#���HR��{C������(�W˚�}��ۘ��)NeJ�+?6:���A���cbb�u�%��ʛ8�~�o�~�����m�K~�j���I�?���XAQA��� �0������/?K]h~cŊ�Y�TP�T�����o�Q^��r��@�V�(�3::�={��:��U.T���/��� B=jA��	/1�E�c�/�@���S�^��78�(-w�x���U�Iɮ���ݻ��Vm'|�H�hoX��q�����}mc�Xz�f����?tO���_��xM��{p���������*����E�a�� �N���!���Q$��n9*��GN=�T�۷���s}xyӯ~��mE�f	��k������'u�x7`�*)��C�\�� �yg`~-B�m"�Rvz�\���ݹʚ�5^{�k�<T�ʕ��׾6w���\��$�gF���A�
RH�y�
4Z'�%	;
��04#��	F9�r�Y݄��k�����,N�s@�<NW�1��1����iO�fpR�S�N�7��bS�ͪ���+�랻\�!m�	��a�t=�fv#�\��xe"�0(O�@�7)A0�[��9m.��tU�VF��;��7a~�E�a�@�C)����ǝP��
����0^�~g��9�Q�����I��Y+U5��?��6m���E�Zu=��|�k�eH�n#�k��b�8���1kĥ�YV����|��U��S�{+�+W������*�W���Q&�;��2���A��|�+x��^�*��h4P�VQ.�q�ڵ�����^	��|������'oG�4[DR&�ʅ�n�Wfi]U$�@���b�E�aA@����s�0��t(�
v#��B��nޮg&�I#QL|6��Ƕ��eT�U4�T�������k�c���[���Mh���
8��_C�0J=��4+3)�{����}�k�/�&s�Y��kl-�V������,��v�]���
+��Ğ�{\��z��\.���Y�⩧�nݺO�ܹ3���N>0��L��$��Y�SYHq��aR`��`�$���\�A8� �Q�y�D�����U��`��������OB���9W�Z�j���4��2j���L������Bo����͌���;�(h(f�7�h��8w��m7��׿���E'=+
�]�t��$JI��h�X%^	�}�l(����S^�f���$���add6��[&o*WBZC��C���f	�M��7:.~A8�H� GV2��kz
m��4Jb��R�-G���y睇'�x����ے�t���4ZJ�M%ᒅ]%|���������\��߯;���}�K_�I$I�.����e$��<�H�?���~z���FGG�b�
����m�
���e^SA�)$�4ɲ��i�������p!e@A8�0��QdE���.��QBeu6�vîH�
�W�K&''1==�������5�kk���Z��i�g��K��6��䭕�|c��,@>[���N;�=}��&� �s�Fd�=���ZnwDk�Rk!��`�`*	�V�avv�R	?y�Q������C�rv_����*�����s%@�A�	$H�cO	�^ m�?Z�K�>�u�0����M�����)P�%�p���OBkbD��y8���2��&�>����9?2&)�{�[���
�v�i��K���c�U�8��7��4pO���k�	 V����<N?�t
U���R	�|����隻�-��Ä_�
)�|����_�c��pL����Y����
H��aJ�R߂m���=���߳�R	�J�z=���r�Jf=�&�>f�A�p[뻳�CC!NF��Ul��h�ЈmL>��%(�gzz��o4�۸�ĺ�۞�����(%���d�^�������_Ly�*�
fffP,�+��X�v��G`�/�4[����W�B<� �E!*��BS����b����)���`vv�Z-�lݾ�bf��\1k:�a�e�B��示*��m�׿���o��{��O=���/�ّ���_q4������<A�JH�(R
�-	
�jQazz��O~����9���~
�rT��[��A�%�摄���X�����3��X,bff�J���'����G�vd޾��;
>���;.���0v��m�XO�0==�3�<s'Ls-�
0��}���a=��&� 0DA��
���O��L�/���ᇝ���k�ї/ ���K����rtJ��ii�+n�2��Z�����oY�xR�I�o[+;���� w����}��TP�Vs
���4���kB]�w�<�Q�I�X�A: 
� BfA&ះ�L�(�z�m|��g��5������]w��,�I�=����1�b�Lp6Q��B���{��Z�����g+3��"�P�uiM9�\T�I�aZoJ��g�
���g�V��f���
�/?�!`B�|Ƒ����"�� �@!��+;��k׮�a�V���qc���F�F�^[�Ju���i�1'(�@T2TSw`[�Sg��#��7��
<�6��tlS`u�n�D��0ǵ��_@��$�Fi�ݻw�{�c4�MT,199���:k'L�0�f��W�@�A�vDAC�?9�rF�������P,S)�����.PFk(m�����h���@�}�~$N@C�N�G�ox�Y1r��R���ANa`N��E�ܺ�7���uT*�J%
�F#����IB�A: 
� B6�0���)�X�jՎ��I�J��@u�w�2�tl|���8د�Q��gt���ڽ�mn7�}��:O���C�B*�<$�P��]���4�]��+�@�AQA���(�6���큃SUxï���TrlJ6v���Zì����~��fe��M����n2�3?��Y����}�����
oB���]I(yxU�7���7��[�f�<}`��ޠ �/�� x��?�0��\V,Q*�RM����O�
H8Vq��,��b�ޅ��P!�qYxX��
�y�;����������p��w�t��8.�\�`QI�D�dǐf�t)�"�ܳ
5���{DZ+Z�T\>@�X�{����K�
�;��A 
� B^�3������k6��eT*W���~��{N��(gӇFl���L�NR�����(#|�86�Ρ��?���n�T�шm��\���ν IR֚�R�?qr
Miή�6��*8��NU�fff��?������s�A<� ADA`0k��)o{��?GH�Zc��R[�ڽ]�ea���0�$i��ʼn�L�Wx������{�=,l��w����>ht��%�*)G��[#�ׅ2)����i{7�I�F����T>)�	��+B�a�� �� $� ��
y��󎷚�f��O��5���Z����ֿ�)���Lb�O[����Yӑ�Z�o{g�w�ٵ4l���~��Moz�]��_`%~
�N'�b��!R8b��M�=�q��w��@�IX�V����5���[í�"�� x� ����p�7��l6]�O��ך��-Ķ���sc�'F�ch�Cf�ؙ�5��4Z�d;���r��G�����.�d���l1~}�C�<�Mɚ5��Zf=*n�c-�[��~b
��ؖU�R��
���a����`�T�VQ����-�&$��(� t/� ��ˉf��T
�P(P(�����E�(����`a��/����S������8F���V�{�g�}v�s]��"l��FDv^D�ı�4�Ӏ�# �������Z`��R�V���J�󡟉l� CA�l|A�b��y_��rPJa�R�L�tH�5���C����������������=*��q��g�����BEN�(��`��0A��QAJ)�]�.l,v���;>6��ؘM��L�@��r��s��9����!͉C��!᛿r�|��(������ߏ��bhhc##�I���a~NMx��RJA�(� a��M#P���A[�m�rժU��V��T*P�$�����D		�4/�����JJu*���So�(|�/��g���z�%�[���@)�ª��?<<�\��B
@Fq;��A�_DAC
	�U���O/^�qC)����V��^��V���n1���$���A�. ƔU��Q��cj�� ��rx�S>�w���#��
�xxCCCX�d	N:�Dl۾�*��N��(i��P A�RA!�֚J��'��η�����gӦM���u�V��V��z�\xH�o4����p��h�
����L������ec����o���-oI���\.���>
������/��0W
)�B�����'���m	��x�>�U���R�#^� �3QAX@�ę�X`�N�-p�U�ׯ�Ta���m
��[O���O�F��+!O��?�w�ʯ����ڻtEk@+���孩uQ�	�CCC���0����"@�;{�]�9�9(������]��M7���LOx�A�M
F�P A�(� l"�B�x�����|�).�B�0!)����{��&L\����SN9�_��2��	➆���ߙ*����m��t�6��V��PE���180���Q���?}�q����j�#p��j�35��G{�?��^`�n���%X!��� d��j09�0�[�Y	�n���ߏz���>1���k�ðIfr�U�@A�!��Sr9�������Z���ϧ�DY�_!�tA���-$
�,�p�ng��,xm�K���;��vڅ�5TӚ��"��D�wM7b���w��vQJ��S_����dH���RF�u�)�)�BA���HU*(��{aO�����׾��_�p�`����_[e@ket^��Ơ���y������g�������CBA2� A��P5�jڭ#x�x#�����!K �1��t<[?
�2o�z��8V�y�s^��V�P���d�JC�;���U��g&��k^�pB�\s)��My%������� BWDA����~)���Dp�ۍ�w�l�lL�n�v�����V�^��R��V���l��$���o��~�vA�*�Pvo@�h4P��0;;��k�n��g?�~��d��^�=�ΗN��Qc/��3���g�'���_!QA�`����e�#�Va�K��O�<W:No_����F?�"�������7��h4R���'>'��+���P�/��
����7���V��/���Y��D�Vs�H\	���*�`*�L���D"��`��®H���L��츛W�A��HPA��� ��c�9������#�/B�o`����{.~�_`����o{
T*�'���}.w���?��G�ֿ�M�R~
�|�ƚ5k]]�B����q���ᤓN�I'��[n�ſ���I�&L��$�����^��E�>��FVS�T�A���@�G�p��K��Y�‚'E��A$h?��8S*�P*�0;;�z��<qc����/L9O�������F5�;�z���
�8y�s��S��n�T*�055�<���r����i#�[O��g6s7"�� �TA8�2������f೿q�u�$����s�9熢�)����|�ڏ��?q*�W{Ҷ��i,�xq�:�l����͙�<�b��s�9��DI#/ ��S蔿U�F�(�[���/�p� �p�(���b�q%����d�Ɋ���0�_���T*�T*�\.���V��5&Fǝ�oJxjW�S�:�L����M�/��~��4�ʥ+����r��R��b��5IR4�VH		���O��
-�T�>o�AQA��dnl8�`,�#lK�z��������O��n�����dpZA���G>�L�� IDAT�����e���`�ڵ[����Qn
Hg�-�ÏK�� � 
� �c�X��
�0����;eC�RA��������!P�O{d}FC/�wX3�es���%mՀfgg133����؛h���A$eR��
ቹE�G�IA8LDAX`l5!��`��c0²Oi�X̴�oٶ�	����?6(Fޣ��q�]��2�A`���u��{h������իo��gcIn@���A�9DA��	��C
�0��З�z�[>[.�Sɿ�?�gs�c۬���1��ﮯb飵F�I!�������tx�-�*پ�z���0`�J�
� �|�
� ,,�䑶����gv��OgZ��m���}*�LI����ī5�M��]�?���U.��n�ufT�P*��f�?�	0
�(�p ���
� � 
� ��­������s�m333�ο��g.��?��)�i��T��G��]��+�Ԉ���A@1��������2О����(QAQA�.��!���R�?��h��}�͉�^�0%���M/#����J��5�c�XǦH�ZھI����v74�e����\S���A8@a��?�v�?6�_���l����F�c nY}�v��Eb��e�S+-Ĉ�Qُv;QL��Qlc������\�?~�o���قD	H�AA�CA�������?c�����'ۺ��V�޹s����x�M�Z���>fGNap����\!Hƈ���m/zzj
f�5����$��@� ��p��F\��z��m333��_M�@���n{c߶BK�C;Ӥ��K��\0�\.c�ڵ���;e+�\�6/�(� �(� �j���T����/�M��كr��j��F����߱c'�X��[(�����h���}"i����ϰՁ�ܮg]�zhܸ};ݣS��:*�
������Q�W$@a�@aamn�' T����K�RPH���T��&���l����D��Qq�0�/���,�r��c[P�RA�\Ɔ�.�x,�#� �� �(� �	�y��`������<���2*�
��:Z�����曌 ���Pd�W��gb�'�]Y�^A�ؙ�5y	�b�?h�;@Ö2��l|ReȔ	�y��N	�C��ط6�r�P 	A�gDA�_x�O��T�I��<==
��O
@�o_cees[���� 1��g�g��\��@9�?)���(��2]��S0��P.�q�ƍm�	��C�1D	A�WDA�'�ҟ$�S�ϡ�)�~��N���g���$L���Op+��^����F6�G�D�F`�p�>��&)@%Ӹ9o�r��:��*��2}�	��$(�t?�	��P �A�QA�n������y�ۯ/�J)���L���݇dw�RO��
�����>�ImWI_��
&��j��h8�X,��_ޖ��0�� J� �<!
� �<�u�
�����r�y�-��ۭ��X榛n��T*���৿�\8m�y�<�$Ha^@a���(��-�w�ڵ[���ےS����P�������f��F���R��w_}u[�ېV�0�L�A�'�Va�au�#�6	�T����������IG^ i����G�0���tr䍡����1�,A?J�v�����R�@�(�����~�s('bi%@�� �(� �)\�x�k׮�233�J���ql�񘔀f"�̾(F��(Lj�d,��Ȋ�Q˞o�|�ŭ�]�e'6�cı-��5�xIPT,񮫮
���A�'DA�C:����xn�NY_,133�j��f���TmG�8�؃VR��h[0}�L�8I�u¾b9�-W�
5���(��_�b�´F�M/��k���mm	�����G�v/����@a�@a�	Y���o�իWo�����m۶����P��"k{+��F����W#Vڽ�ҟfj�ؖ�4�F�Xk�����jA�X�mҤ�(4@�f��P*���|g���<?A!AA���S��Vo���[���zH�7�y�V�25���(���~U�q�����cc�7�cSߟJ���|^FT�}:f��Uyl��-[�d��ۏ{�b��<!X�� �1�� �����b͚5[;����=�$��l�
u��6�'�6]$̻8�]70pO)�d��Ѱ?�����B��Q$�]�+h
$J��r֬Y�B�='�� �#�� ��
�i���ПP����?;��˻��ω����c
c�G�υ�,��¼J��t
.e���}��ׄ	G���;�]HP�P�VAJ�K�g��=/_	���A��BA�;���A$ɿ)�����_��H�{�>����W�$�NK<�0?�&�?���Y�&:�X�f�$��� a@� s�(� s��ӇD�B ���P�����v��O�N�ͤ�����H�Aa���/������V�P.�Q*�`�w'7"� J� �!_�� s��:#�S���v;��|�ڵk��ObϞ=(�(�����7�"9n��^(��=�����|�+&dP�0����
��i�Vf:�C>����&g��y�fwi������~JDV.����.�Q!��a``���8��t�R�\���~���K���I���h�TPAz#� �p���?���
��\.ߘ�?><�$T�DG"�+m�r�
��V����#��?;��h�����\�!)�?�?����$�����)�N��u��9/���q�"P�\�
0���V�������<hA�0� ��BR
0����V��3|�ڵk�g��߿���G�ZE�Rq���n�2���	�����
x�UoG�^����,�X���/�g��h�H1y,�6m�R
�|�B����ʕ+�r�J|�3��/s!�`��f�+�Z�y� �t� �p������`���Y�_?;;�Z���~��?40�i�ch��4L3/� ky߸i��ݝǁ�}ظ�\��x���d��\�]?<{ٳ����SeAk�����v���	&���0J��	� >�A8X�O?����n'��~�k^���ك��)LMM��h��h@k�뮽:҈���Hb�5�?yǻ0S)/ؽ*�_=�g"�!�"lڴ�\QahhCCCX�l�/_��+Wbǎ���a��((hh� �p��@����<�ź�Z�f���z�z�Y���ߗ/���b�]@=6]~9�2�z�~��Bk���ָ����-�����'�����r�J<5���Pi�Z���B���N����� �p� �pd�@JBj�pY�jm��j���h4h�ZN���'?Pr/4>���ţ{�T��
=E�+"�ui��or/.�t9rQ�O}�Sv?�g��3\q��,h��peA�<W�$�.�� ¿ � 
� ‘��+Uj�R��>�оhd*6��?������R
Q9A��4�g�.�Ӻ��h=�Ѡ�+�t���k�lb��d��ob��9�7&��K�(� s�/��em4����>�O�O��LĄ�(�2mB��"�l#�� R
#���5���F.�C.�K����6{�PJ��+�D��mn�,|`]`� �p�� �07P��n�"����@[�P@>o��g����>�jj��7��j�\���c��)��T.�={Ъ����r��F�|+O8ӳ�n}��4�M�Q���Q(��ׇ��`hh#CC�I��4`��� ��A�QA��^I	���k�-^��:%�Uɡz����h40>4��я��
���r�7��z�P�����b�����گ���B�	�TՈ�H������������į>�Y�1�M�q@�A�#DA�#���m�X����-�066���Y�N�2�Ґ�O2)Zk����
>s��/P�?11�tE�̣�H��כM���ᤓN���O������e/{(��9�V��^�F�y�c0<<���a,Z��-�_|�CW��w�
�O�xA��� �p�,F��^o��������G055���iPU RH�'�8}���N�%��SNA�Tr�6���7O~6��
�YXC�~�
7|�Z��c?���h=����~�>�,��V����{Q�VQ��P�V]8P.�C>����FGG�d��q���λ�y���nH'`A�9AA�#�)T�s���v���?y��?�_�=�b��@ɾO
�-��r!LW\Nj^�"�E�@T��T�-����u\��WA_�v�Mu�Vt�|��?���ǩyh}��@
���|�A����]�a�-?߻�J�����n�m����LOx�A�G
F��lgA�_DA8�$5�G��
wN{��M�>���&'Q�՜`�xb*����_�����i/~�D�����+�G�� ee}#��O~�
��̎����p�4	��$��d�<��o�+��?P���K?9�ߏ�b���V;w��`(���k�)�Hª�tA82DA8B��4���R�-��_
�N
�G;�=��SO��SO=���iLOO;��$�l�b�|�2_�Vf��^�?��c�l�l���r�����/Y�K�.�W������Q�þ��~������ I�(� G�(� s�֚����m�n'�(��5���k�����|�I�E�J%�dKUv�lٌ̯v�}����.�@R��B��.]��K��/~1���N�KO�`?��?e���b���A���N�� �aA�?�0�*��&a�XW��W����R��Z���<�w˖-����A�W�/叵��7oj�l6Q��Q�TP.��G�+���1L���0!?e���&l��A�QA�
����0V�}Ά�n{���5�\[.�1;;�j��z��*��+�C�0�(G��s�ۡ�NNT4X'C7o��B�H�V�(��(����k���xv������$��i�?)
H�OA�9E�� �J)ms(�a_#$���L���
�����1yӿ��'��p�\v������S~�
�tE�(V�J;+O)�L1�t�#��}���@�M�s�����#�c�Z-������~�x'���!��S�[@e��^�je�l��=F��5=��_A8$@aaU�r0u��Hا�>���Ⱦ^��ܸq#�q<��㘚����d*�떭��T����4���>�����e?�ܮ
���(�߃�v.�T���K].�������b�
�X�'�|�b|I=�iI��*{�Fj1$�Ga^� A�9�	�$�6`��Y���*7��T���	����8�����m[����v�*LԎ��~YC~�B~�R������E
"���g�m��%�Z-4
T�U���"nD6k�k��'mS�gaB�(�_�A�yBA�9�
��R����T�9#���سofggQ��R�?���)�	
D*	R$��{$¼��1�S�@�������:�@
@�VC�\Ɠ����)��Ѯ�7�����/�0?� �00ᕪQ)<��&���V*��u'�S՟��H)@�!B���F���r�=폔�Tj��M�R.T�3d��D�(@�Ma<��H�p���M	�V���9x�5a~J��J)�A�QA�	d�R1��K�o�P��INq�9��H�~������(rBz�#�GQ���=@#�DvoD#b�/b�ENU�`�������| ��T*8��G�{\h����:�� �(� ��mA����^�������v���E����ާG����G&��D��[�4�M4
,݊�Y �o��� ,,�� ,LХ�׷	��t
����O^R�<��*�7#��K�(� �.�V�;!;[�?��I�Z�V�I?��_� � 
� �Q���ı��OU����A�~X0v����V���.�҃�%E%6��X�A�QDA8:��<��o~���+\�-��B����ϓr����i�kS�ߌRڌ�^�OW2��eA":0�<�_)�(�����W(�ɖ������9�IAX DA8�8`ū~�w캁����R��Q#�(]���+@GF���[E�?y
h~��D�=�b����0��[��,��B:�Y�A��D�h/@��Le2S4Z-���!�Ϸy�.��@ms"���@�v�����z��HC��4�U��z�r�mÁD	��r���(
h�C��h���!=-AaN� ���k����>wn�P@>�GE�P �#�8b��h�`��MP"�C)����m�/��ʆY�7A��|>�|>��o�}]��y�#A�( 
� �у+��oL_?
�
�B*h�ŗ8a���r�?9F��N�w�9���5H'
+.�ą�DQ�|>���>���@�w����oVf� �0ψ �pt�=
����6o\���`*�<�f#����ޛ��ͭ�}}}���WB�A�2�� ]������w�w|���,�<��{�{D���i�(q��v�`�������ع����(�����T�o�P@?��_��λ���HHu>�G(� 
�� B��O{w�gv�������3;N`���U�PX����.R��m6}�e�Q����Z��«�m�lX!��h�P)wH�n)ܰMbDZ�c�L/��O&�*�x��H'O&���8����;��~��y�(��Ǐ�3�fʟ�Ťk�FҬw�i$I3���fջ/�Z$�*4�F�ڻ��H3��_����h��a�}���N�/�k���Nw��X0`qf@�j�6666�n��j���@u����rD>e��H��hf�M
���,
nf���V����j���Ec��Hn~��x��.�i�Z��/�����%9ɓ%@,��X�L�I����}o�=�h��i�ۙ^P��p�?~�+e�}|���r��j	�C_T��բ�r������-�������(�����_U����F:�N����?(����HX�y3�W�{�7f���o~���fsss<PoZE�����T����lLm��T'�e��g�jEQo�99Al��O���V��v�����lnn���ۿ=��W�{�I��d��X`�F���~�N�Q��$�fn��n��N�s.L����;޳��U�T'�F��3�	�ey���QuF@#E����>��u0�����$y\�^&��,�� U�;�g��G)C�9o��ƫ��G�������t:����g���7n���K~����K��LB��������%��Og�7w�(��t:������v>�쳹}�����Rv����������F���&�U�\��O�I�9s�g^xᅿ��~�ݻ�G����0�������F�>��;w�O�v���s��4�ͬ����j���˹|�r~�g���������$��$?J�^&3�$���#,P�$���$�&�L�L��~�m��]��������������������,ggg�F��K���|�K�%e�")F�2��)�j�/�������}����jVVV��t��tr�ʕ�����ݻ�$�֜g���`/Ƀ��{I�EQ~Z�~����B@�jU�Z�g��͜�^�v�ڷ<x�����������9==�`0�p8���sRE�i���������.ɹ�}�o��J�����v���r���ܽ{�Syr�"IvSv��K�0�~&���,��`S���Ю_IDAT$�$kI����U��9��z��_������A���r||���Ӝ��=�00����v�WWW���:^|\������O�����T;LY�sV���X��
+)ˁ:)K��N���޷�/��|�;����f<prr�^���`������q�>/I΍���>�.?������t��t��|��g�7�����6n&����?��dr��0F������LJ�֫V��!��sn��7n�����xQ���Q���srr�~�?Ӌ��I��]YY���J�����|v:�lnn���ֻ��ٜgx9�z�)G�eR�3*��@K@X"�Ѩ>�k5�l@�jW�\��3I�����W���q8<<���qz��xm@=P}�ܒ�������lll�������+��+O{�)�}���Ou�Y�]'�,`�L�5S���\��d+e�I���|�O���K�쟜��ѣ�����g8f0ԟ5>D�ҥK��nu�YY]�[o������)K}��vX�~�FQ��T�%3�(x%�g.�;I>h��ϥ�?z���������xn�l�3���;�|"e��ȓ{���ͤ��a���z�ߢ_�%#,����);�L�	��t򔒠�R���_��f��EQ�Ν;���=���Ϭ�)O�}8�ꃾ�����?�R���L@}P�z���:lU����Ku~>�rao��?Ȥ��j���#�KJXb3k�)�e:I�S�V�}����I��Vw��R���'����W����%7f��j&ۅn���ֽ�ǿ��_��[I^�	?�V&�x��|�Nr��?���~��p̄��$�R&ۅ�k֪k=S�2��{����Vʲ����ө�Ϥ��^�[�>��?^�e?�p�LV�P�Lw�Wg��B@&���9�?s�;�g�����\0�35��A��I�����f^�奔�0�Q�陀�
r~���7J~.$��3#P�Ͷ������#_������a}�N?��%\pS!�xJk�\�gFSm8s�׌�\p���T H&?�v}�U��CF���	���?����X�����uIEND�B`�PKEGA\META-INF/manifest.xml���n� ��}��ۥPuq�X�f��]�`�PI(4�1���ժˢ����)���;��b[�d�I�s4�J@sSH]��s��N�b>�ULK��n����;�9
VSÜtT�
���tax�@{�3��J���������ڒv a�.���!��`e��5BH��*�ɩ!�1��NDP*��_�\�uj��~WC�X]+�[Cd������}��HK��,�m�nD� ���m������uc�.���sB?�����A8f=4u��p~��]�Ws>�7���u�}����6���~k��]�C���T��n�k]^�+�4��T>$���#ì�i������9�F/��8[>M&�Z��_��7PK���ePKEGA\content.xml�[o�ȶ&�>�"�{ùۺK�d��ӗL��N{��ʪ��ԄȐ�2Er�bY�Ӄ��҃�>��/�0�0���O�S�_�/�Z$EY/%�rl`WZd0��[�X�����2��3��4��kT�{���jF�����W��<��l�z��ޫ��
��V�p�__�{���=�6ޛ�ќ�2罫�7-f_���~�����{׵��j��(Q5�~�Y��k�wP�g�m���+=:;���u��F_t�x
��F�Q�7�899��AQU	�Y���R�Rc:�ƜZ�ڨe�̥i��e�]rܱ�zy���.{q�~�e��ږ����,�v����(mKX�)ژj�����ԩ)z�����W�N=U���<�n�UⅣ_ް���ç.�Yh��(/#[s�)��W����{�a}j�h��Й'h�Y��f0�'5^(\1�ℼ�~ȉz�g�$��;�^,fk������S5L�!���Q�a�p�w�/��6(��K��g�����iL`vtn5�Y:
8�mZ�#_G�Rw�`,ǵx��s�y�u�aZ���S�Ul�J
8Qzj�P�K���S�����p�6jX{F����.,����e��tRXK.�s\jLdZ�Vչ�ߵj m�T�56����r�}�x_�wd�	�qʒ �Y�#jAk�4���8��At�J�*��2EwN�,V���߸\����o
5}<y��T�̀��4Ǚ*ai�4�L�[��M����
#7sz�Gj��w����;.�һs�pL�:szy��C�m��AO{ajr�1�|a���)�bJ�%�������:���$�H�Lc�vVX��~��ɍi���U��S����<��P���?���������������������=7���F.�_��_��g�i~�fm+qL�a<��y���y�>�Ȥ�s"��dl��������R{�L�\a ���������]�p�+u���<��X#�z��AnO��Q���ʥ`ɳ]�-�/���s���^O�x����E����w^�W�W���ٮ��G��z�a�qt�Р� ����hH�>�rA�hw��[A.���nW�.H�_I�����&��74^�V<�����{��l4;Z8�6�+�%��N�O�{�a
=m7�q=mw�G�{z����Z�͸��:�K��b=m7c�u�Zb��r�i�ڮw�z�h�4�ٻ�q
��h���j,1��r�i�zr�>�]�����z�X�W��{
�����-�
s�����[�0
��/�;���c'lF�*]�3m��K�1��A�t���Ty�����i6�צ�cQ�./�Ęs�*��
E��t\	:�3*�9r���	�`��ֵ!��D���l3�&�Ԋ���a++]6� �U��q؛��]]�Xj�ŋ�F�0{O�K���E=t�03�oT/�!A�F줶���=�_�6��	��y\o-A�x=0�W��'��j��UL�\.=�8�Y������B�J��5UE-o��a�3֬�-1c�v�+w�^��y�Gk�n���+OG��}�BM"���OV��h�y'y����A�y�笳s��K��n��q=o�w���E�^��/e���Ԇ�2P�j�Z��<?^g�{&K�����`�:yQ�N�w��ɋ2t��x�QP�N^���������E:y~|R�N^����'%�P/���󓼭���d	:y~RU��<?)��qQ�N���@��(C'�O����2hA'eP0�2�F���F��Q/�hl����h�� �2�F���Q/�蹛a��iߦ� x!��"ڷ"��2M<�v�������3�M������
/�-78�d��{��TQ�դ
��ɛ�W��e"�a��h��k~�ϥ��E�M?G3L:�]��t��f��G��p�&#���3mk@
��'i��<-!�d�Nq,����:G�7-��������PY�z�:��Ï|[[������ڙ^��5m�����5�kX���}�u�k�XW�X�Y�o��@����f���½7е������w\j�����Zoa���#`�����(��D�ck�~䩢;a6L�g�H[]j�m�P���#�#AV�J�����.n�=#=�4AG׊EW7��6R�&<��bs���9��Eĉ�h)X}�ZN���:u�ir�-�������l�_�4"%ңxF�+���JKKs�Ek�0P�����麘��>Aϵ��z�w#�s]{�lyC9o�񔞴f,�R�����_���3>���{>��uA�%x]b[b�؞�J�pG��Em�l���ِ�8�	+F�0��ԥP���_X�~�!b�~P0]�Z��W�L��V�I6���������^?���͖�[���y/��	��2bJ�����Dedֱ����R�1Bϰ�[��ص5�|��5u5gJU�E�p��6�����ɨ�\\Ko�I$	��&�ĥ*����.�I*��DF>H�~��=��"����&*䦫�:��$Q�3�*^�y����z�6��Ǝz��:.��fѪ��_��e�U�|�;��X�����ܙɝY��l�D?_�[��⹹�M��U�GJ��+�zn�@d�(���>gI̋g(`e
k�����*�in�:\	hjW��F���o�onĿ���YWꇴ`��n�1v��Q�9g�����m�K��������E��V92䨮m�(Cj��dV��\`\��[��@�±�݃�D�D]&�퀀D��Q�1�}tX�Jdn��H��>9�M|��'*�Q=<j�!&A�\���>w޹����9�~��s�ݨ6�NNʳ�� /��47[�+�٭�v/��w��Bզ��=M�_�Z�Z�0ge����xet�-J��(B)�Mm	��Z�V¶�K���w0��㱨��X ��e<,�p`k��'1&1{k�F�������Rm�gX�m$�L��\�3�\����]��-D(�PQ���4%)���r�R߬d.���$*��ݶ\�r�@��kRQ�p��Z��4n�Ϳ^i�C����:����-�,+��NBK��x~��D�RN��kM��		Z��vir�]QZL�I!�rrJsP�3/��d9��H�S�S�0��l�l��b�s��ؤVl.Ԫ�H	c�s+}[���(�b�3=�v��e7��k��A,%�J
�G�9�CE9[+��j��!�x6P�x��H�����7!
seg��K��*M�=u���j�S�$ ����*�E�jy$#X+P��?2;P��\�3$wH����7H�P"� ����gX�\��.�}�����}����orMM|[��=�:nd˵�Rz���P^�VZ��ͅ���e՗�TZR*Z��|I	�yb̪�4wP1�(����Ie���l���;�� ��{ae ��ҍ�'���99ĤZ�2�Ӭo0誔��H]<�*e�mɥ$���Rk
M�������'�S�/�.9��`���v��dc��I6���X�e�=>���Xң�o���(�؈���;����o_RT�3�B^RPp�(��m���Ytݞ����8�H�M�TC!2b�������%oW+�����oY�.3	Ku:�k?��v��U�ˈ���qC�E�T��T�pw�jμ��%3��;����p��{NaD��{)�	v	��=���8�am�JN�['���I��5>���>���|�,nGX\!�q���F2Ŗ��~\���V��yu�����5I�q)�b(��L*�D�̼�&
�0�=e�k[�-:�����N���*�6�K��w`�M��6W%y.M�E��6n���R=j�S�Z��o'���'�U���Z�\�h�h���e,���Q[Xl	EգN�L������K�Y��H��7J9s6>N�@4	�&��n��vꤪ���;>w�O��/��\0w�zq	j#g���I�T��Z�@qIk���*�UIS����TanŖ�>�	�{�Zn�ǃ>��!��F����a���I��
��n��-K���(̞i������&�E�����ly&���ҢN��Z*���\�۰_�cC���N
��*3$�J"�%Ң�lT��8K��W�����g�嚜傸֬x�F��;�\����f���9�fNפn�핌�u������'k������2�x��w��������7�J� �}�tYϴ�^_bUbu=X�B�H�^o�`%2%2׀�-���2�]f\e!�Mn���5��uM�5�SK����V��\U ���5Ƀ"���>p�7��6�'�-�+���Um4;͹������z����\����(I�￝��4������L"��Ʊ��p<Y��W@.ldyn����e�Z�Q�7��vG��2gJ;��<��)�ųL�F���9�|���C-�J�e�7~�b�4�(<�VW��"�ˑ���K�2I
�2~>������8'���������L���w�60FTe�ݗ˒S���F�XΌ�(�s�"׈���7��/��e�[q�k0o?�A�Woˎ�"2�3b���r��SU�0^��0�H�s�H�h�����`���TJiE'�h��E��Q�J�*���jKf���X]�]#ͭf�r*����_�d�ى�P�om�c����l��1�[�0���]���l�Y�΃V�����6����`�君R­�p+�.P��P�m��Z�*�Qq(Nn6-KXE�lZ˾RA��
�OZ�l�l.���[��e{z�BQ*�	 ^j��vu�>�3ņ��eZ��q����3wkL�qZ;r�7}Zw-���/�^{��V..m)�߲��=l<{�e��i�8^�`��9gM�+E~Ӑ{"��З�/��n�.�
�o�`^n�ůt�p�� .�ػ4v�d��(m/�i����8Ʃ0�](	��9�K���1��\���w:���S��\�Ux�C�⅔)�{��QBe_؈ܛCj�-T��/jyUo0�3���ΦO�'�3_Q�<yMü]~�'��2-�V���\z��¹�����
���n2SM�3�9�V�}tX����f��H6�����>QʏQ5;�f¾\Fms#g��Ѽ��ڈ:�ͦ�YN=�\�p7�f���ϔ�
l�$qG7�0cN�8��r��~}yy���
֌�kw%�d܊�J��v��w��Pל�r��N���b���,�/���κpm�rm���y��ά�o�_��\�-.p..��>��������;���nqm��Z���Q���ZoOHcܩvx�N���*iN���3Dl�ʅ�����9d���vc{v��6���rђ�����"�ü&���d���%֋�4>�x�
K6(�b�r��ܸk2�g��i�s	�-2�LZd
l�[�:%OPf�N��h�{�o]���fz�z�qC�ǫLe�5�h�E��񈍳z��ֻö����8��I��כŞ���lYh��x�٢M7]�3hs��z�~�X�]�3�맧�jz����8�뺑����f�(���lxnkn�;�I����0�3�o�n�O�̶Y�SW ��qf�&�.V�43~���=�4�a��0�']�,�-Ʋ0�
�Bc�/��i�ul֭[ϙ��N��E}��4�[�N=�DZn=6�j�nJ��_~���`%+Y����|�	jޔV�j�V4�fn��CX`q/�U�go����䠱��U[��1tqۈ��>�^��D���[��w��>�g+��Xq�����=�T�"����ę�͐X��X���z�a�+3��kf�������H��=�QOŝ��s��i**ʣ���˄�Pu�,���}�Rr����ig�j�
�l�Pt��+����G�?�T���j���GĭL\��,�ul�L�
�:������x�70�4����*���v��Ma(��:{�G��m�\�z��=�^\�4�����Ւ�ͼ|��� �/CJ^~�7$5�ty�3��N��,�+�c���٬�ن{n��S'K�+z�&�l�1 ���͉cYɗ��\E�7�����$��ϗ��l|�M4GJ����b6�=�E�R�2���8�v0c�ͺR?̢*�f���b�Kg�R#%�'�skV@�w6�q6i�&�uZ��3(L�Ȝ	kˁ�8���x3�kn�m��2��*��	t_{�FQ���HS���̸��zM�.� �)1�2��MmYؖ��U��A���U�?27C���	���2y�f�gmQ�>u�={FO������(JLnޙs}��y��9\�C�pr�����;�M����^���B�qƛgn��Z	O:ѓ���3�R�z�2� �m+�iͼ��>�����_�/�+0?̞����s���C��/�<R`r ]�D䐿���'3��7��t���f�E��z���k�*���cj�m��P��N<S���f�����[Խ�fP>�=V`:l긑G6S#��6cF�wW�����pH�1�5�`+�+���h��M�R�hz5��g�t�$a�_Q=��O%�8$|9�:&~�yR@g�L����t��D���Я=�3����y}A�s]h��+��������E�� ��{������t"�����U`:*��j���v�5?6;Ĝs�}Uį�?�:L(��K�����i<HWW�&��D�MD�=�NN�9Y���M�yp�-&�W�����"7wp�����Q񗹵�2�vn��ָQ�n�����[��R�\c����Ym�;;��YW���|��"��"g�ɍ2��Ֆ�h疹�i���_����x�8�Ln�A&����';��YW����
V��wp�3J���r�uGYS:ʤ�l�����x���(+���?�ߥ]�5�����l�b{�J���*�S���p]N%�*��خ�sõ�z��)1?\��F:`���ח�Z�Kq�})��$�H$]��z=������A�FiuM��K*V ��4�\oc}6��ȼB�8��[X�͹92�M;΅�&�f�n��+ԉsY��ڤ#��ƹ(���l�m�y���\oa�6�ȼ6�q.�7�6vKd^��8���X�M�!2�O��bx+�Y�C�F�n��8_�/X�I����_tMu�������c�\qwm�f���>��q��=�T�3ωܿ�/-KWT����+���*�W��\*Stg�C�)Us,��+����>�n/�L��u�qm~e��2T�H���~f��\����4��r=WZ߳�$�c��[��ĻF��^�V��8�-�O�����	���L��-x��E@�s����Q?�f)>��v7��v�$x�J>yʛ��������$/0O�6�A�5ŅA;��HR(�i���e��I��<k���G��UfگBt׿F����H�S�G��;%M�I�s�Cm���n�,����<a��}�$\�������G{�����,�l'���;�A�[%��
��T_��ԥSg��L��������?\�?\�~�;}�rv������`��͐��p\��y�j�_g�d��O�ᤨ�݈����;=����q(�M��?R��߉��uH�1�( �\(��\R�c�����&0�!��@V��@s�J�SM1
.Ո�p\��C�_�P��f�0抇��k�tԨND�ȈuA/�>S�At��1qǹ9RLXᐾ���t�Q��x�'�/�D׫��e��w�h�#��l:�?�������L��������MA�3fK�=��5�{!�X�r	���|8���r�2S3�x��n�4����9I8LAP��0]�:���v�i�' v�%��<��D̎͸�jڠN����b��0�>q�=��k.����i,,�À*�W�dV�e���?�X��G@�'�	
j#B㭒j����#'(��x�e�6��M`kz�
,���Ԫ��)0�O�ԣs��257�7�
g#��p:&3Py9>���]
�$�ą�g�A�n��p�#>j]{��\Q����,�0�s����_8���^(�=�;&��7LC���ީ2M��ۗ����Z[��X���qCr��c��: ��tF�S�]R7��ύ�Iׇ��2�Ĉ��o+
ac�B�^!�n��b)�>-������bw�����2:��q�bZȐx�4��S���0��`XSR�}��;����|��fl20Ga�5���T�9��Uqs=�cLO0��������d(��>����Hs>ޒ�0��G�.(AÀNMkqmS�&ȦK��@� =-HE��Ur6��xF���k��Cn���WG,�v *7����`h���%��Tp4>����@�8I9Cq~���~�Y�E�$.:�N�כҗ�h�d���Է4X燁f���������ֱ���vHrpaU�(��C��bІxk�O��Y�Jbv��rrS��ҁ�L��t��[�V&�]���zk1C��c�&�&BDQt�q��d
J�����+�@�0�H���5����{UY�U xa�]���.����3��:��
W]�e�;hZ2�7!�����/�� ��%8p4T1��������p��K*W%PE2`�*���� �������0�L��c����B�#zEc�3��3p]�}�6Ҟ�*�5h�j0���EUk`�n���3��9qsט��sX�_�YC[N���ϰd�����)�!q�������4'>p�J �$-��y�J�iNj|�ʜc�1S��i<�G�#<���٘	�<�qפ��@�`|���C�i�#"(�'�����1�) �a�/s��o���;狺��oO��ہ�f�f�'��S�C=/]%Ϻ�#���@|i���O�"],U�a�B�s23α='�4O�ٱ��)����]_��?�F(dR��N�qΦ�V���E��&��lC��J�lj]ś�O1��74���l�Y>�����\��3@��N�fw�aXe�*��~�1��^`��W50���!�y��3ս`��5�����QK�y}��Fo'h�MP���p0�S�N]k'W�����LH^�18B鿳l��>���R̓�
���Mm
�����̛�n���������[�
:6=[�܊M{��MT��|��k`��BJ�f7_�����8;��t$�[Ԛ:)��暵��ԚR��ܿx`vV�m^#�?�i�zT�`Uzi�T�V��N�:	����ީgMy��/��
��O��<�1mt��]�W;H��=�S5��"Fju�EC�����Z�0qJ��q��9郐9�\��M2r	���Xl��	�'��^�l��`�5f�?�P��A�1�x�#�6ܑ�&�T�W�c�D�8�_�"�å��Ն"rR��s����e0�B�5:%+�������1n�\g��[��@�kBR�J��"�E��vF�(R� ���V ��>�b�D��ǻ��ND�?��8WB�[>�D����Mύ������h�<�&��d%��*R���l��X�4C%*ʄ��r��jC�ԩ-�R?�6mܖU�+��ف8X�݈hX�2�@n����M)*%S(2W���o|��R�D�(,$���F=!T)��O|4+Y���7C�3B8�������L�@bc����u~�)\���s�6D�(䖁���:fqH�d��KB�ʒ1�Ut����9H4�
�����T��v�/a��
^	X)%�K�U���m?�d�F
D	����,��Y��A�G��O��z6sĦn�X�s�L���e���s���0et*�4Wd�2I���:f}��X�a|��1�?D�r�OE2)�%XJ���t}��Y�oqv�;BtLs!=)��tRJLXo�W���<��1&}
Ӟr�V��5B�l�O�8�|T�ݑ).^2����~��'7�|ন���747�W^��!�GHa����~�6?�&��B-�qƎˆw�D�b�<0���hCoH�����KdC���%0�}P���c��@���H�wS�����a
�����[2��q�U����M�
0G��ۦ���6]1�V�#_��iv�F�8�ݣ�^3��$)�%�l�0���{����_�*%��F��QXT�4�Qe"ƣ�z�$|E7�'2
yEp	����l���\Ebr�\�[�����(.
�R�C������6{!)�7v��o7��
����>�bڳ�_�})���\(����k�Iiq��^l>�Jur��,f�hNj{(�����-%��Xec+Ir:R)�%J������;���#7 �i�x�&^�,�h�˪��v�m�W$�C4W
L�"J�ӕ�jLW�m����RpJT���
��K/H����O�\f�q\�J~�ꉍ��Ⱦf�9؇�;��y�[u���*�l������O���Ps�h@]~&oYvY[������=gY��D�v��U�	$�4���M㡧�k�z���!^�n�����R'�ܯd,h����M�hTez���ᢰ��I+P�Ģ:�&��JZ6 I�;i���t������"��2A���1��jp]�6�j�Nj���������\fG��N�G[���J�+<#��J��ڒ_��i�"���;��<aLgO�{6��A�s	������R2����D�%��Bu�+��e����ZG�>��l���l�5��J�'�QZx�+�>.٦��S��y�q'8o¨����v8�"�j	�aji��*OR�I0����
���q��gH6�fϚ�9��p\�0;+�KP�>�F�O���l�R�0�۬ܐ4��4\X���~u���>e�d#�	�Km�:�8%�vfk/��e��b�=����\X�M %%����{\�$��7~�wڊg���ީ9��Z)a)&m=
Z3!�[�d��a�Y��s{�8�����h��R�Ʀo�γ��r�/��/r�;������EꠅA�H����0�qWϚ�u�r;����sL��HVq��j��Ms�W�Q�)��#�Va��֙%s�q� �i�N�Ύ@cjgW��R���P�W�QF=�"��%%&8�p�T	�0��fi�O���>Q
S�BX��4�I#��t`j��J�U���e/R��ka��8�q	:S�3��߫�O���'�XT�=�Ը_�����!7��z̙mI�[)�
���h�B�!=�7���	JM��t�F<̮	JM0OM�_R��7�:�2��K��� �G�S��r>���>8�ٖ��C��������-��
��A�����P����xS	��HsY�$͍�-�ڴ�$ּ���`��ϝ".^@�7�Iw#��@ܙt��W�v׿02�܆��ʐ��р1�xV��>��U�yտ�5B��ڭ�J�%y�n��L�d�Nϵ��k�g:1�Or.dg��6������\�}fIה�����D�ȩq�!%��Vm
�J�.qƎˆU�m��l�LY��PhbVjXt�@$pS�z�Y�/��+��N-�6�2`O��y�0���`�d�2AʄBʄ$�yNlU5��d�}lԥx���lF���4��l[Ca"�G�����iPjlf�J�d&�����u�N�'	�E�'��ϤС����A��L\��/�f&��O�+���N��2Tyzl����
-}�:�xs�6|es%�z��
�T}���O�-���M��!'�b��?J��
S��Gu��u|���0�4�����q�!��@Kzf�A���c���qcZ5çнt�,s�\Or�Rs�F+ɮD��Lw+�p��\R#���"'��?L�k}�4L`^#�TF�Tr4Ѐ�j�=!f�>�.#���F�_`��F�Ly��(�lJ�)yf��<���Cc�џa�J��8��wz+���[��Ʀ��1�7y�`��R�G/�n*�eDse�^�'���~�f��Gj��w����ީ�Z�ku�N�J3�-M�(���:S:.j�����s��9�~Zx��໔C2�b1��J�%$y0�(�9�W�I�����\�����/{i$�����`.F�a�S7S�o~�WHO5���f{�S��-(��̔2S������5��c)3�$>7�CS��1����?d&E�YRd�m��)��t����0�[:s87���7��<��ܑn&-&
ˇL-��3�6*w�Ȓ�J�;��lw&fb�F�-J�:i҄Ne�|]6� ���0�l�H�N��QBs�L]ղ\^�Y]Z/�A3"Z)��P�=e���pBM^X��h��2�H
)V��*K��6��U[֥Ld���!偔R,��Qs��'ɪs���Z�f8���i�	�
��ɖI�ff�.�\�&��5�U�6�O��L<Fc����T��<�t�q�.��h��fϭ���$���w��o�Ӧ��{;�_7�0T���tL�������������9�m��HH�T�^=~^�z��$�M
�2m��{�`Ȩ�����R}��K���}���$���/yF��.X�z�p�3��.s5����;�-,������M��T΢��+��C� wʚ�(�$f������P��^���٘`�t�y�PE���&��,H2�T�B���x����ճ��G�>�����\d��2�W�?��^\zfJc��X��Ɗ0m�3lf���y*��1�5�,o=��]R$�Y�ѫ��lq&ͬ���uƙ�0�'�,f<V�
s�Νޛ��tJ�����\K�,S0��
 ��\e QV<�A�N3$���P��<TO���]�*
`J?ёJ��F+)����.{O2�]c�Ĺk��eW3غ�'&�
����6��͑>��9tI��n<Kg~h�;f%��g�'�_벥�@��.��A�Q�ډ�"[(3�
�f��`1�J�iT�H*M��&�t����K[&Ϝ���C���|���s����G��������|�gin'dE	����	����u�ь�����j��X!�"y���?yC�p�H<}�	�p�:����Γ�|km��ON��#P� d
���`s*^�a0jw�<p�ַ�3F��^�)��F)Yj���e�m�g=V�~w?K�`yd�i����+4Q'<S\�S��V8����P�1ɓ��Pi;��hTa�r;!eߨ�J`��%M����J���}ƻ��U渚!�����4,�rP�u�~���x���0�>��w![a�}������T��[!M��k=���RL(I�۰S��xc�#Vk%���IJܼ�t�1�\�0~xSJ%:JKMJ�,Ғ�\fw=�`6��z����#��)[�O)?K$?o���2�l@G�iI�� ?-�9�ԈgTğ(G��^�E�A,
�v��)����T��y�P�PEa�Cs��^i�.�[�g�!����fˆ��xK�ϰ9�24��/��>�(v`g�c����Mnל�k�����fŧ��׋����t~�K�p���P��n�oU
m���E���7��~c�2
{,�ߒ𗣣�S�m��|�"/SR� #N�B@�E�a�*P���[��̈́Xr�^~NB��/�=Ce���6�z��lj�,@��T�0�1��9�>���`j��hI���o4��u���f0��U�ƺ��<#{�_=�B�]��%aA�b�/gY�����k�T r
*�C��y�}�QQ}3��dj����	Z��7@��{�in�}�d���3�j�ȑ�CKʳm����ЕJ��w��k᲍ʼn�q¸A=d�i�����=�H��3h�����
���!���c,�$8x�4��ր2j�9d}���q�o�e�ju��Vyq�PL��=����UI�ɨ�9.�Y�t=2UL���2����C�������
��'�8��{T�P': ����rɞ<Y`Up��5�,�M�%PK���[:U�C~;�1wF��
'a�
t�:I��L=U�Ys$T����<��e�§��f�g=�v�w��g��*fE��P��HUl0�7.IQ��$����a���cX=�6d��^��Q�r^hh��݈�/��/�)�O��/�ꋝ��/��9,�����������청�$x�:
��S;���
�Y���T!�ni{��M���Y3=g���-�W�Y��c {Cn�V�J`6xK}����k��]�8�gИ�O��X�;���X�+ˮ�h�9,X���h\��I�ԃ���c:J�<*a�<"���~��;&F�z'��% @%
�P�ʢ�d���%ApF��@鍂9��U�%M�������E��I�N��{�
6�'�@�8����¿*	z[�Ʊ��	Z�D�����z����<d@qç�9�r��
o�h7	� ���#��Y%��f�C��
2&�/P��+)-˷�˭���鿕�5��}6�'f
�~d(�:���[R+��3�2��V�+(I��$-��E�,��������:�\��H�\�h�h��4����|�x�H\���6
M!�<�]�a���k�S��►��%�=(X�-�A%b1 ~��3Q~����DG8��4���}o�o�������Z�Ji�-R��rn�0��Q���͑Ó��&�sZ��{;��红
J�J�!|�'�M�4���������g�hB����S�/J1�u��8����C�gCW��q�}C�lk"Cc�)8�ǿ �L��;R�EK��r�`+��bYUx;��L
���_�|.$�4�6�̇��
%��(ee,�9�*!�nH���.E���+�.O�7�2Ѱ��ҵ}��v�;b� xGO��U7�tN��E�N
L=�o'�V�;�ׅ	3L�?xw@�8��� i
Ow��eT�4�<e�ejP��c����|K�������/��@��JJ����,؇�u�p�բ��� �j<�6�l)c�ڗ&޶�_��RE.�����3�d�R5.�9�����e9G{�?hl��2B堭���lʣ�0Fl�p��@�*�Y�_})e�(]�M?KzO��{�WsC��9�}:�q���j*��T�_Ib�1Kq�J�P
b���O��e���Ϝ6��0fp	��0sՐ6�F�3���͈P�
���C7���9��N�MI�(��d��m�u+;Y�$Y�"k˴%]o�����-�:];.����TI�3���N�I�I���R�sH�<4�����!7��z���G'����k�\�m�۠��@)B�@��\���p��IX�Y�.
W��yX�G�crA���-QQ`TeGőDE*�x����B+�a���qvK$a	�T5wڑ�Ĥ(0�%9'��#L&A�1�a6�>����p�"���J��g6��?���W�ޘ��f��G�; ��r�^Ҝ(�&y{�~�����/��ٌUt�|"
��i���V�|��w�Z�Q>b�_��#z1��C�i�/����6�O����O�|�������#���"�m�ѹ����.C�Ah� \��xJCa�+2x*-z��_�>}t�J�{��61��6~�N8��a�e��)�q�]���PҘo(,���s4k�����mQ��?���L�Wx�R@���1��k._
�K�l:}��,+Ox�^�N��jQ�΁�������Jb���ry�����P�L��l�A��[�E��)\�H����n����ۥ�{I�)�L��vCA��IT�2T=0��eQǜ2��¯;�$�%��ʟT�ʤ�9
�
A�����U��Rt&�Q�6fo�w�x����*�=%��:Ⱦ��;���(�u�����(�3�o�k�JBI�앰#Ev�D�!��[�(v)�v�x�o�J��l/�����
v��
Q�U#��;M�<�o���/"
��;��1�'@�^�m�R���l�yZG���B`}��'�xw��/
L��l
�z��4U�������^B�n�ԡXš�P�g�*h5���o�Բ�� �
!F(*W��c{ש�AGWwD�K�cI�[%�I��D��M�*<?;F��#>=�QLõM�Gu�; �̣�x��ܚ����
}ќwd�T`��.y���p��zEb�`�ӑD�vQnW�Z��镴XZ<�6��7�l�~S��p�F]\��pBmF�3�t�9�h%q/G�ˍ�d���
���t�x���>�������h����<������>$%���'��uin�J�;ܪ����ZSw�6Ĭe��w=�5����+Lk�\��LY���~`:�%H�%�&q'q��*�*�7��sf�̞�)���R�z�����,�|���������kC��-u,�t�H"k�jԏwZ�9z�r킭�蓸Uo5p�����IG'0�k4X
��F��M,����x�
Ѝ��@8L��Y3��ɘw�8� �GвgSY�z��h���oy�Qt~��o-]s�?�
[��V=U�E�®𖸎��C���hD���x��i�@�E�TxgB�7�3��U?y�3]��؋��`f���B���n�E�o{�ڭ1���WS�L��p�j��\HD��.
���A��C~���B�����t���b��[@U�B��{��`����5�
L՞�4�ѦP����š/Ъk����/�=��yP���4�E���ŵi�=��!��6f��|�^�7�\���,����Tc�Jn{��p�ߊ��{��)�[8��I�����)�8Suh��Y���ˆإg�X�?�g�(�f���3\
q
-�n�jL���<� �8�VsJ[܁�=4'煗60E���*�v��n*�,��$
�)�"��J]Ļmrix��[�`�PNj��������c��4�N���ߥ^�N+�~��D�f���~W����W����q�U�����4�1^%�Z7�:ˡ=� h�k��D��v{��ߥ�L��?���^���_=��Ne]�_	�r7�mMe�%����Ŀ�n���AV�^v��C��\:��{bª��jG�����ŀ$0���T@���ʀ�D��Q�s��Ԙ4��1kZ\����G�v��'��^���.�b1[C�)�qMI)�Ԡ�2�n��OT
E�>&L�x��O�Ur:����w.ܳ^>9Kb�C�g�*���*���
�z���A��9��h'�x�ȴ�hF.�-��7\��!ͲJ^t�xz��M�>��
����k���FړV��f������O�R�V퓦�����_۟5�g1��ٞ^�'>��Y����<k�f%Z��KF���_��F�q�^��4Wm&��N�!����}�4]uR�� ����4�
�2�Q=:B�F����B��-$�u8
}s�Y%g��je�z�6�07G]�g�Rc2i�B@{ѯ"��w1������:ɰL�s���yNO�'R�����<�o
�/���t8��f�RL$��I�F��W!R�k�%dzٌ�\`�53��$�?�#�6��00����fp ��,*K�ˍ��+
�`\���7# �;��p%�gW�[�@4텙�V�1��, �(�p�l�IT�����a/���mʉ(
)�ǦghH��H��tL�`_%]���ST;�Fۧ`*j
䯯3[�~U���$�Z���O�X8
S�f6k/�K���ohq�m=\a��Fܯp�!�Gj3C�.;t�'z�a��Z9�ɣ��UV.�9ŵ+�8�Ulj��Iz:�;���0���G:�t�}V����:Xզ�������/��6w�F�WA'�X�Uk�\���W����}����J~{���YG�̙&�����F$<:e�g;�H?����OTfN�B���]�g�'����U�\'
��O&�� 6�2,��uPi>1�B��zb����7�%�nnz���@������)�{�[�նdZϴ�`�ԅ!���sd��N���$�f%?���wH���M{�]~�b���o�5�|$_�%m�%]��96�z���R��Z�|�Z��|��'a5��4/Ϝ'���x���n��|u�I��cX�-Pp;)C�!(9��s�����
8����n[lP���x��o���,�'�Z�#����U��[&бwY��>L�>��x'�YXl�x�:(҃��R'=��Թ/��PD�8�������"�'*م���m�;��L�L&��g�O��P��>��Oj��*�l&�(��tw��Q=�g�Afp ��E#�1�V���;�U��������چ;�(�	=܌j&�ϥ��(#���׉^��Ͱi���h�5�گC��cw�w�t'�l��H�B)�go��}�t��$Lj�+iq��n����Ʉ�^
`��L�� �y4�2�%�ϋ\':e��ߦz�cz�ˆ�umxπ�DbN��i=M�==�%
�1������Qx�ݹ�A�#�5�kj�O����k1����a�6u�T�oJ��S�@��+��!�E0���<�����0
#=coO�Q������s.�=��Kzg�=�^�@f��epa*a��d����<U�����u˗��F�����5�bܳ�{��X)�A�9c�9�������;f�������!�BaX���M��WU���,fB�Z�V��rj�V���^'_Z�?!?I�R�b3:Qɟ������'Y��Xj�LhC����5E5��l�Wf��F����Mߙ	�N���s9��T���ԲM�~9E�ѵD��G�h��iԛͭ�zL���;Y�2���Zۣ����J��N���]����v�hu���F�s�"�3G�L�;�;�	h��S1�*��qpg�SP̞�̛m>g}m�0�J7y�
���h�]<�c��G�z���?qW%��Aq@sDU���~�gt
�e�:�O���}�?�DŽZh�k�A��M/���p���'h/���ƣ格�8�J��Vr�7�l˜�	������q�0����|#����\��Av�!�b�T���`LX@d0P���|�}����h����~������{߷����ㅖ�l'�/*.�k�tD�7E`<�.UA<>�,�%��eї�������s.�8���3ES������R�N|�G,�;Y"���zH�;�G|��Hj�SJ��A�<V�0S�Rj���MG�+}6�N�3��*,UVCv�)y[�]��'F�֪b>V��ʏA7��k�2H����G�j�r���(}O7�J�#���%p�Vso��<�k�T�Aw�(3(<�0qW	ٵ��7��dk�Pu
Cb-z�O����q�1��u�MV$��?�44<W�0�\�6�-�:�����=�'��������/�y�5@�"���	�VCg󈻕-f��HL��u���8��׭���&
�개��&��ފQ�59����E��z�Ҭ�3
o3=A+;�.5�;'�@������ѐ���'2����h�x8hqd�\1�
տ���㗯�#3�
��w���ͭf�]�T:�ޠ=G0�H�}�iŶ�BO(C���q������`�y��;�]nj��\�_
�����N�P��2�;�4~�_8����TC��'���'#���
�]�𻔓63+����N����81Vĩ�LDF�]?~���Hξ�D���ߟ}y����=�0%�t����mj��upsy�	ʟ}��|�������������'g���������{r������JK��^����$i��I<���`W`�1
Qb>k�f�u38��F��;���= �v�`�`�Z�TH�E�U�#x*��zP��n���_���7g��l4�F��8 _�r��Yx�Ip�Nm�#����i]��:Z�Ch�N�?���Ą_N����i}���=ܵ���1籌s�Z 羫�����E�ԁ�
4�ƚ��!��|�U������G��i`�~@�˦!z�#TV��"s/��JñL�VN��RUX�ܛA�J��T���M8�2�e�v�;����s!����꜐/� g]0��Q ���6!X��T��/C��ݪw��\.�A�c~�v����G�#uM�S
�������zJ:�дP���8C�
:�RmnsY��gC�%h���J���A�TN��� ���L+�YW1�G�&��8V	�)?�O�`n�q�o�W#ؘ�K{�2@=�6��m��(XA^�  �y��P��6�N���5�ă�������[�A��tH
|G	َ?l��U�M4>�����ٖ��v\��}C�&Q�W����q���Kb���ܼa�xq�y.O�x�8�����"�ǡ�k�
5�N���P�i@_r��$"�}��[������?6$FĠ�r6h��vc����LZ]���!�O�Yv����ʓ���3-���p��)�%4����@�TcsF�+r�5܈�01?�1/��4c�*�T���"��T\'�Onr�R	�,I�Sڤ5�2
2����z��h:�qNyj�{��ͤ��
d�����Sy���
y����`}�9�kƹ'�"�g�]>b.Q��t�@n��h�$���������O���%9�������G�����������������������v�ߢ�_�
r���=Z`@\��}��
}����4�/矿^\��3X-_n����G(�x{�����^�+�^��Bph��Ϯo./�O}����_�ç�ϟ_���ۗ�{���0?\B�>|�
� /��/�q4���a�{�A���<��?.������t���p���P^������0����e9�zy�]�ix���������%�x{{���������ˇ����>Y_.���3�0T3���_���]y����z�x}��,�7���|z�'��*L���OX)������%<����3u�S�3v�-��>N�|��������K|y��|�~�|+u������,4���W:%����_Gr}E�.~��^��a��}*�3v�ɟ� +M�T���_<�	z
�.\"�B��g9����h��������@n���9�P��d4���6ï��%ir���L�("|����d�T4G�y�UP��� �k�J5ؤ��^s�"����f"���	u����V�Է�m��
�P��t9'�����D���`�A�����V�a_��f\��Ԃ��c<��c
U�w�͸��2C��BD�<+#a$�ie�?��&��1�&B�C�V���#���&�!�Wt�
�5��G��+¢f��p�%{vx�B����`0���>?�@~	����υ�g��m��h��?��0���r��;ågjf�
r�Y0'�����$]8�2��xb		��g�/��s�]6�^]���n#$�r�">��΋�]���n�� :���f�/�?�� �O��1��/�G�x�F4��)z4��Wޑf��&����fl�Mr����TP".l�Ml�LLdc�~���*ݿg�r�P9���c���C�sG4$�@�E�'�ی.,���c�Ӈ4dnE7�'2�In�F#�9�m�O)D��`a��Q�c���M�d���eә����NBg"�t��ͽ����&L�!n7�p��+aʰlf1W�\�"_|�:ϦI'�˧(�0'��a.�(
�=�4����c&�[7�(�|9�9�m�����H����)�dj#)GFN���	V�A�g_�"i�B��s�6�S6o�cL���H�Y�;usy�)�ӌO�d��~��s	d��<)�\�!�%�ж������߭���'q+�L�G>\3��kũ��=t�CAJ�g��th}Gnh_S@�1�,
���)Թ���ҮZ%�?������]~3Y�������]B-%�o�4����]��Ď�=gV���mV��%.�<�0�;�N8��jbV���*��i��t.3Y�c'k��l�dmt�]�UVs�M���������a��(���6���c�����x�+�Md�����PK���NVFPKEGA\^�2''mimetypePKEGA\MConfigurations2/menubar/PKEGA\�Configurations2/progressbar/PKEGA\�Configurations2/popupmenu/PKEGA\�Configurations2/images/Bitmaps/PKEGA\2Configurations2/floater/PKEGA\'hConfigurations2/accelerator/current.xmlPKEGA\�Configurations2/toolpanel/PKEGA\�Configurations2/statusbar/PKEGA\/Configurations2/toolbar/PKEGA\��h��emanifest.rdfPKEGA\�0QEc$
�styles.xmlPKEGA\��܏�!meta.xmlPKEGA\ܖ힆�T�settings.xmlPKEGA\���(�C�C�&Thumbnails/thumbnail.pngPKEGA\|�5ׅF�F5�jPictures/100000010000030000000300E4B9002A2830C766.pngPKEGA\���e\�META-INF/manifest.xmlPKEGA\���NVF�content.xmlPK��	

Doc/OoliteReadMe.pdf

%PDF-1.6
%äüöß
2 0 obj
<</Length 3 0 R/Filter/FlateDecode>>
stream
x��]K�$�q�ׯ���.��
LO�
���|0|�-¬
颿o�2���kvǫ�Xlc���_<�b��?����;���{����-�K+����:�ۯ��s�g��/�}z���=��'�0;���c<�&?�m�ç?������F=�xi�\K�4���_���r^:���
:�4��1���.�-���(�3�W���-e0�!�K�DxoKY:�4���h!��|˰���-{�%�gfE��.Q��Z��D:!�Z'0^���_�������ߍ�{_{���o������҅��Kľ�����G����λ��?�H�ɮ<����=}����7�¥�sɗ��rL�>��է��5ן�{�@���S��^�ǟOx�������p�2f�B��;�����:�9~����0�1��>��scL��L�n�ba�0��}����O���A|~��Xg��ù�b<?�0�8�Ļ�`�z���D=�fh2A]>|Ty��_�����C}78G{�S��Ǔ�x�:/��x��ZS��0���O=��;�!1��6Q�c�)�8O�3}_����7R�{b��S�O)}��&B���L���=6V֩� �O6�W�7�ٿ��܌�w�z�82�2?<6V/V��33���O��B垔�3�<�bz��Sh�˫~:[�7�g?� ���9��_��E�����Cog���x�*�!�����z���nz�4�*��l�c٪�P^���
q�M���af$�e]>��le7�<����,k�iY��f�MS�<��+�b`1����m4])�Z�4J��^�_O>U��e�X�)��Z�,�[d�/�h6�Č,��������.̫���K���7�c�q@���-F9q��I�4�����(��u2�3T1Ȱ��ߝ�v�o�np3��,���[��4�����s�Vb�j+I���h�qEo�hV�f�5����6;�����`Ջ&��+��$|�DVy=�(�[-%�:�H�ʠܢ���T��[��DV����~5,���O`���'�)6�K9���J 4�S_-��`��b��4k��D�A��ɀ�/���)s{��-x.�,�e#����u�'���`���=Q���l��>�k�^l�%���=m&�J�T�bk_�F7%9H��6Ҽ5��,��ӕ�t�������Я����\a�p���,�Z^d)O�.�4�<�1��cj#�Wҭ�K�t큖,:�����=��A���X�MV��q3��5~�A�򦟍��n�
3V3�������ue������"�2�m\���͇�C�i�21C�P�c������4�d~���W�_
��e����!o?����E���/�3�o�1�}��-��_ʖh\k1�tYY�*Y�l�7���9i-�#���k�E���7�_2���9O� ����A6"����n�ɳ�9�,�*���叺�E�^ֺOx���I^n4?�y~T��q@D��s�!v}�r�͗ICyԥ?�|��;���HOF��K`�T�J:��
�%�W��f�>�d�B��E@I�k�e�㽺Ȱ/�Ƌa'�4e�������S�p�NTX���S�}���Լ�3'.Mc]���C9]�[��5�I+ΰ��%��4��ɇ���J3�_feI)r�Gb$̊EG�/:&Z�W<�Of��W>��EF��N��5w�b����9�wҶ�̑VA�1���KQ�jݬWmDz%ܟL"O�퇽�fĺq�������oZ��#�p%���	�]y�d�(c�
WI�|3z~�ܳ˓ꔃP�n��u����93�9ܣN��e�[�S���d�GdkԷ��T�Dx$������H�+�+�X�g��=>�"��.�;��{��%��)c�hw����2�v+�Of冀5;�����w��]�n�%���,�nS+�i}0Z�xfW�o+�k��������@$cYs�f�v1�\�k&>��wF�L�k��2w2��"�v��^)Θm��g�f�@�FJ~���88zYj	���!.�c0yauqI���:�Y���/����#����fu�;M�k7�?R�x�2֥��S?�8�(��[�چ����D��6����o7^������5���oI�g�UPLj2J�?��������n*!�����}/���������_������Y�v��F����r��7,�@�b��ol����t�V�7� ��t��ޙ��צ�&S���,�:|��;vX�N*=Kj�"�F��[�<����_f�R�ާ��Yn��D�oZ�t
�&nڈs�޿ɶ�R�n�0�A�0s��6e�u��rޏ�~��ł^Щߘ�+�A�KZ��4%��Y/�ŀ�n�W/��,�u�E���u�gx_��Hy��i��'1�i��)�~-��iV���_�-�@4�U�����G}��׃E+��сm��:�ې��c�M	���@��XwU����^��dP�!HU�}��}�^S���ϋ�i����j�V~S��~���"��3�����3��Z���ћu��4X�Z~jW��
�v	�W��Ć�>~6�������GX��{m�B6]��Z�OfDy1'�4����}F}x�]��o�����ʖv˯��p<Lp��N{������uw^���q_}�p���U��l��A���(ୢ���m*>$��-lL�)&����5a�D^o�+K=�����8:(��I^]���һ'�;A�/�v	㗕�-1��������:?�{�#����2�;k�JtT�Dzy?��ٜ��}‚#_����Vc�Ӳ?�'�롈-�O؟���\���?�j�V.�읛���}���C��%�F*l�c>8�gg��I�T�}�Q��vv�D�b�����ڢ�]�������������`�n�f�wۣכolw��~���X$��c�f҉��
{s��R/��'�].��#8@�?���_/��Y;-E���#S)�W7W��Ƒb�_Do_�
�	��!�7�;7�L��$�9=�;R�j�W���s����F����R?�;��Z����/��es��H�U=իi� }RAh
����
�;��'<����6e��uc��ڮ��"����,�mK������z$}�g5���̍f�^]A���[�S�aeѶ}����.�$��w�.|n6��4U[�@�\���
��&���������q����RDy�N���#��8_�����7��ݕ.�nz�k���e�>�>��}���R�Z&��o7��O�sxlǽ΢����m�`Ņ�F�>M��� |_lޟ��]����ԕ�D�]�a�R���gI�0|_���J�"���Y�W��#k�Û,��e�`ʮ7{�{�ߞ���Z����7I��%�2��Mnx�v���!F�hUD�E[�|3u�(���LY�ʠ��av�v��*�KZވ(r	+��/
7Q0�^�98������e�}����!BI2gi�OU�o�ϴѮ�"L�R�@�k3蔽��b��J#F��}�	Ī��\cƺP�`(F�o/t�I���z��K��y]B�!�P�����P��]�A� odb9d��h���^�᠋Hg�<�=&�]bFG��;XI/(q�Z�:x��;�(�ꌤ�_��q���y#�:��05�}3���U��)f��etT��P��@���21_@��q��Z��K^$�O�����X'��!�$��l�����f�;0�I��F!�Dy��1���l��	�Jr�j�2�XL,���C,��I��/���x�T���5-�4�%��4Ȱ36kR*�є�����J��
�t��!��8d��
/W��B0��L���[G�Q�V�y�"㟨c�x5{�R%�C�h���h�֘�,$:�B3���[S i�~A�+�U>_ȟP�ߌ��B[T�}T���92��vZ�Ҥ�Ǔ/�T��N��פR� P��0>!j5�Q�)�	�񯆶��ќ�Obp���C��	�E�'�az��u,��(�Hԃ�n
y"����F���e�,L���ER��;Z��p$�h�^��1엦�>
���Z�JP���:��ڨ��YLj ]b_+�
٩����3�˲:T:�r��a�B/�ͤ�PY�(z��ś:��Ȩu���|�"\U,�B�1p��Q�#��Bf��@hGk{v����qtT��W"�o<D��x
n��@NY��8��d�!wA��1ĀEY�Xㅁ�m.&C��H:�����C;�7���z6ơY�\h�C�&�
���`���һ����h6�����5{���u��4l�ޅe�h���
;�r�k�;la�G�Ħ�f��]ȁGK'Iu�CT��1�,�o��2��
�W����J�˜nv���qa�%�W
�3�\�GT�)��06A�%pu֎����a��U��A���F�\j�����Җ�>��#�8(�ş�#�T
��c.̏�4��c�@�nLl� ���T'6�ͻ&2���ﺰ�r��r3����Sc�ZT��dKX���	�V5�	��D��;s-��`�6�@	�]�pLP��-�8֕U
�����3NBS[F�-����Q��[���!�#��-�9��®�6m(��OԖυYۮs�IG�u������v�9	vd��!�i��T��@����`v��[[�G�If�+(�FG��7���V��(�xLi�����Q�J��i�-/x�D�`���1shAq�u
���HҼ-m���"ז�L�6���j��޺�
t��$�9�%!�c���?!I!hDy�9Y�Zż�`-��`֤+]�+Ԩ&1�(����Ta�����Z%\W4�q�dZ�U�+*	�"�*&d���� �d.�G���d��tN�
��L�#�E�
pd���K���
"�D-����s�`e�!KW�d�6յ�b*J\��J&�~6k��a�&X �M�[u]sVC��84I)�D���v6���PՓC�$�!@���j�^�"vD�E ˌ�#Û��B�)D�O�p"��9�t�J�l�X�9����)�Д�jeklE�
�)yS��4��2�����B�h+=�>6t��!:�Q��v'n�P�"t�:DGG�dOt����ю��σ��l�Y���3i��
���.���ae�N��E:�YJ!1�E�{�9hi0t��)؈�H"w
��SM��R̡:8"��>Q��p�n�OI�h;vt�5E��ٵ�r�7�F�p�-��6� �s�@QEЖ�Ih%P�o"�+���G���N�7�V�"��>v���:�GHD�čjK9�!� ���K�̃P␜���e3�}��� )
�0�B�-�'��fn�� -�1n*���6N7#�Xi��u�a����E)��O9jTB.�����4i��|��=k|HyB�+1����E���i��Ǥ6:r	�CG�H���^�4q'��va��<�1�갅b����duEa(&�"N
�Cw�ő�iF[�e�����H�4~DMm�0G��,m���`��s���@HEj�8����L!����p8H���`U�2j�h�š^�Ej)8u����W��.丐��;^�`@RY�Gb11KB���u��
o��!�ż�A��%����)��0)���Z�.3��M�T�*�;���
��9�`�(}��,��E���c��/E�m;��T��Uva�i�G�m�<МΚ��Ѷ��)F�8)�I��KML k<Z����m�T��6YB����J�5"E	bLP����[:T;wX�&�׸�y\�mAlc���0Ub�y�	�����o�W{\p�r���$,�@c*UGè9��=,Φ
��T%��!H���	
����P�+FEG� l-Y3L�hh7{��n	��,�:���Y�A���h� �L#�
�  �u
�9f��LB�7��kǃ=՞	�
��Pʳ�	��`�J2LB�V�:����n�Dф�Y���D중���=N�O��oRm��5�
�|f��ֱ�n��Uc��E�",�?o8�h�"2��R�P��G�mU��xu��~t0D�5`lV��}�jB_Cd6�f�9:B� ��,ZFG5�)h'k�5�J"����m�:"PQ#Dn)�T�5��xѬ��Y1l�#�2w���N��Z@m۶��Bo҆�03�f�{o��p�<�%m9��vJ�!��p:e�I��X��筆���FA`g���*@S#ٶ�%u��_D��ȴ,H(K��,+�F�#�@$�_���3 Y�U(r"��RB�����R���15IR{�\n��T��t��섴��=����*i����Y ю�n<)e���Pu�-��G.�eW�7_2
��E�\��N#%�p�!PL��ю��Afg�;�~�����L�rBk���4����v�>͢[�Y�V�cN�hrU�:&O�,���Ra%]V�$B��dB� �T|AIс�j��EԡӪr��g�|z\&��I	9��'��fךQDU���V�h��FB����ˎvzHo����ܴ�ċ��Em���k՚���H���G��A�YE��Ht��X'���'z���d`�*Q�[cAX��:�.���R[>� u�P����K#\��ke��
�0:��,�Ķ	ڂH��b]�����n6Bg�mӡB�DY����aJJ�N���u��]�'ʿd�Sr	�:��-H��uT��Jf����/�Ejس�>��o 	(�;f9r�?��`�2��%��j�m�`�qb�u{[	K�@;	qc[M�Af�g20F�hUQ�iy�Y
{%s>��+k��,!���O��Q�,��=5X��P;ptl��H��"\���x!�j�{��:2?�URU#�dJ�7g*�Z���W�t4�P���7]-�%�A;���y����$6W
��6o����,s�(N"�S��b��)\�� �x����H���3�g�NiXmVLB�Ȥ�����0D�J1�6��x&g��3��IEee�Wh�Y&�j�nbP����G�k�J��i���};�lT�fS�ȿ�e�:k���A�>V�f�Q�[�
�I(��deĘ	'�=�d�jB�$CD�l
ɮ��
��F�p����9��N�Dg;̉Dԑ�9R�0�(*���Q�`�`��δ�J�0�B�<+i)��|��.�V�<km��9�� j���t\[@�5Oꐨ��@r��NI�UɌ&�~Ѳ�ú��s�|R)�dL,�YO��EctN
ke����.j*T��Ŧíc����$�Ѯ�y���ț�Ek��GK
^0�	T�%m�����h
qz�Ұ���&�D�� ��y!M���Ħ����bu!���� �7v���9P�3�����4�}2�%m���t9�	�{��8I4�YgM�?"�Y����<�@���ڏCk���J
�|��T�;�j��[�
���d���).�M��X��<�>�}�K"D���QfXo��%�/f�ZK@N+��&�A(D���3��#!:{�VF�9^i�"���v\U�{.Zɦͨ�|�&�C�N���J��"�Q�����NؾbͩM��hgiC��E�粝%���JZ�U�'�|Q7�����!�ml:��q���}��<�H��;��@<<��3��Ly��d��Ԙ��Nԁ���^��fM�v��Wc/�?d����G[b�m��/pj\�=p����c���nt���՞��^�z@5��m�S���U@;ڴC�*�I���2���/�d�4��T�
f�L'3�y�٠�H�#�.6��Il⓸T	�ƇR�����^
�ū�%&
9j�;#����f;�/AE�.RU:[�sk�=@;X�\\��(��/Ū?��Hd�Z�O�rւ����N�MOl
R�$�JnE„����{´37d[�!�v�G[(��A[�.��7m�&�E�c1��E����^�W�5�J�(�B;�;���{�	=Q��FZԟ'��yi�8a�2BB�G2⥥�C��l�>~��D��lj�6�U�=2(����ౚL�&Kyx?;A��h��eFM57-�Ru���lJ�
��1uڙ$�Ԫ@BObB|<w�S��J�9I�"�š�Q3mؐ��.)�iP�'���lʔq�&g=�D�S[3w��$�#��-
�k��(��OJ��L�M��P���O?(�S������	m�i�Ч�]���K}d��D�%<����s9�g.4�;ݜ��<�*��`�
�T'�Z��c�n(�yR	�fj��פ���lgQ#c'�M��y�*�������ɫܬ����C^:�[�Ay�-k�٘�fGP� H�(�]H���͞�~�<�~/�ⶄb�����7:�k�2	Kc������Wq��CТ�U�p\�м[Զ�����O���7�Q�*ޢV�o��v��>�Z�M|��n���
jk\�c�%�h�6_�%OFY\}ܼ�<D�[������lc���we�w
$�����φm0��u#dXd��V�L̟,o�uRv��b��jW\堅v6n��t2V�G��⩲�L�{_f�=��[�p�:���n�f.4���['�s�b�_D{F~P8s�R.Yl��BR<�=���R����R1򄠱k�19_�rbIt���4���r�_45���9�i7�sQ�'[DY���ڄ:�Kd���٦�qtף4(A]�؝wK�m�$�j!���z����L��{P��D�����	é��F5��GJ�Wz�Y���~)�6<�eA�9�e�8^K(k�ULO�k_��r� �ףI���Y�ʇe�}7,��6��1��6$�gҚj$DI���%�AM��=϶���wu��a�*�LE��gE��b�(�CD�y�Ā���ڸCf��J�t���t(
Υ��O�=0�i�)��6-��j�ZԆ�H
_k���8E��\���h\�Q�1�'���
Y@�
����_�Y�T��-K��+X���u�b>��R�Y�	���Y�����P[K�8�y.�kD�ͣ��T�m�\:�;�6`�'Ӿ�(�le����jP�m�\��!P�{��FP�,�Ej5�'��̠�O��;/4�1���H|.�h0~�������N���I�d�t���<E�Aٲ���#��4�Х�!���E�;a	m�)��nξK?�;&(-�?1������AIAh]��O�-�9�h?�nF�QH�vY�>�H*��A�7#��>�M �Dz�̜����_������k�H�8b���/
�Sd>U1�}G�A�O�1���#8֖ѡ<Pɦ��j��SO7���`"j��v�*,R„�2�+m�!�U"p���%(����~��D��a��R`��Ս	�h)Y�W�lV��&u�6��J��9ˈ���[�Z9�bQ8AS���n&����m�M���4d��d��RT�&Ӿ���HBl�g���$�N�"$
��=Z=��-Z	�o

穠�̂�T�}��|��;fA�`�A~ Z,�X��͘A)�IBp떿X(��h�,��8B~IӧeV^%A�jTbocImP�-�u6������DKB2-)�VU��n��n������ίHJ7M�7o(��-[)��^����ɒ�Q�	�h�����"�|�}��N���/����=�����
e�j���4$Hk�o����[�\;O�Xl�e�l�GK�=d�4g�կP���:
��,�Ϸ�����1�L�o��:�J�btٟ���_K���Z��Z_���������~��Z�����q�q�q�q�q�q���
���qK8n钎㖮�.<p���帥���翥�!�u\�u\�u\��v��#�p��u��w}w}w}��]_�������L;�q�qؗ�:��:��:0k����HǍa�D>n;n;n�E�����������E�8.��q��q�8.��T�h�w�w�w��ޱ⸚�W�W�W�W�W�W����®&{ė��5����_��e�(�q��:�q��q��q�ٗコox��#(|܁v܁��s܁v܁v܁v܁f�׷��������|
endstream
endobj

3 0 obj
10121
endobj

4 0 obj
<</Type/XObject/Subtype/Image/Width 512 /Height 512 /BitsPerComponent 8 /ColorSpace/DeviceRGB/Filter/DCTDecode/Length 40332>>
stream
����JFIFHH��C			





	


��C


















































��"��	�������� ʠRG�E�}�f����&:y�������k��|��[t�i�y����c�������眘��K�~��c�Z����1c���jE)[E����%�T_K���=/�s��N5UG�l�	;o�<��yI�$���m��t��\,ޱ4��9%�C���k�ac�b
K���=��E��ˮ������[$�i�"�m���7�3�?L���{�$�&��?A�����V�Z~��-�[S�Vth�A�֛ܕ8�
�ύW ��de���S���|��X��ʢ��+[ne	��9~BQF?�c[c��I�v�����[y��ۅ���Ίݷ���C}�;��.M�<�S��r����37�#����v���P��j��s��ꚟXt�����?d |hrl�i�>�[l���t0}|~�G�e���7H� .TRݦO4�?;��c˫�`/�n�y����]�t�`���e��?�1k��m�.�E���/�ϏX��>�~��[��_;<��?x|���g�AJI	ϛ�]�G��n��t����T��U
oOV��_Q�kb:?����]�/a��)g,Dއc^>�~�Iq�{\��ծg˿��1b�^q#!~w�:��'����my�U2�U
_�U>T5�MO]6͋Y?A�+Z��P���D8���/�SW���ҹkJ�e�F�j�G��yV���ͪ:J˷?��o�@����bֽ���WvP�v��sV��[�Z�aG��oh
��
ͪ��Z{�w†���I�&(Ղ�X(Ճʂ���6u��̤7ͺ�����"#�6γܝ����v���{8�W��W��ޘx�xE�;��X�ܫ���al�E�=�9��Q��g}��=8��נ��g':݉��5�D�K��?;�j{*y�y���
};���E����@p��1,�r�=��w�Ԣ�[���>wߖ���z{�e^�����N4��OI��oH>����WX�o��-������@���q�Zr]��۟�%��r���>/���笫�+*�,ޗ��v�H��������Ų�[l���軚I��#���H����CL7=�Xt3yR<鏻��:o�o�<�g%ҋVʧ�?�3z4Ծ'O;�}�m߾������|�_-��j�H�w�|i���:E������ƃ���n��J�0Zt�i�G�

�G�=�s�JA��'�������%���鹻.��?s'@������?1�wK�^���:M�L�d��z�]�dvُ[������4�g��xWI>ǩ̺���^󯠙
vy�aUY����h�JTj݁�K�����VU?bwQ�@�v����s���' ���"��_���<���:IOUE[����`S�G�;�t��zaj���|��_m�ϮrIH�"-~�u�Z3wW𞿟�W��َ��}q�*��A��E���/������6���og����z�G&����*��Ÿ{؅t�:1Xw�ڸne=�K���|����<��Rc=��+JX��6:9��Yy�>�����fm�hɳ��٤����ձ�b�����GfE���oRg2�������1�J[}��n�Wq|����4�A��d�������]0�߷�GI�T��Y�#�X�U v П����F�:��g,����.�]��_�� O�����y{���s?SC�>�_5QJX�z�;�o�v�F�~Ⴓ�9-n]�O/[љ�=��R˹�Y�����?���K����g��8��#F��
��?z_q@�4�����-Q��7<���w�%��s~��w���}}�0�n���t�A�Ȉm@PW�hb=]�����M-�z���T�[���*i�g�4t[U��5t2��F[�'<N��|��Ύf�wa�'�X�x�}`���r�]�m�+�"��ړ�V�h�4�KcӳV
e!v��_��2�G��L��ǣg'�h�q�e�s�iE6��f����Q�宄��u���|Nu�B�
9������A-�d�gYM�v|g˭L33�����_��a�bF���?h��7�Ex��~Gs�x��[�r�r�W���t옊�Av��{`}9�{�e�I��?��3P!7@ 06"'1�345����:֖�6�C�ɝ(�W�$�P��C���ZV��L͔�q���"Ke�*�r�i.3eD�r�e�lT��yJ�$�/F���dw�)���J_l�v�`V"��E�9X�P�٦/�/�%��}�b�d�D�Pч\OU�i������~��)K햰��[&~+�������)�H���NFG��܊ҍ�S�?�DZy�L���<��g������R��-c�s_��n+��q	؜��~C*���7��2�#u����¬����N�g�\���]��8c_�?�R�e�U�{����L�����#�e��X�A��o<�=���n��佈|Kj�����/�+�R����=^pƿn����X?����:�p[�c3�u4�o�$�z[��%�(��I�cQ}��́Zk�[�t�yf��-�.6��k���<�3��[�*�54��9>�����
�P�<���N"m�Zk�IVL]O�u���_i��ƘIbw�j�v^k�S�;���?�<���BPz�08IY����K�Y2�'\c-kʋeo<�Zp/��\þ(`Zo�����l�ʤ.�z�M��\��J�6((��*lz�5��`��{�q�G���ae��4�C�go��F+�vF6�1i�ɏlrޤ!8�\����Id��p;�> P��w��!E��qA�=���ys%�`��F�/0m�n�Ά���ǔ���*h|@���7!aƐ�LS�$eV$Ԧ�dYe���ͤIK=
��p�͗���|w�|P���	��8n>�fI�v�+G2�>PJ��"WgE�o	"P؅fLt�b���y�EL����9D�w,mbIK!
�v�}���቟/ֹGtwGtwGxZc����t��+�˦=T����)Z]Oĺ�l�e���o��w�,)��r�\`w�twGtwGt���.�ckw�/�ٯ�'�!�W��:�X�c�u�e���N���� B*��^@G�Ng:9�O�j�vL��L�ѫl�M%&˝����֬x�"NR�ƊP���o�~z�W(�c�u���-�A~D��
��d��gj�{F����ŎY%�
h.��ӑ��r9BܼF+@����O:�«��6$Z�,ŎQ{�l,��l ���9Qa��k��S���I8�Y��6u��
W�ΰ����O�c�v^GP�r9�Km�F<5�6u9��!�%��癑���P�R(��&do:�b��_g����r9�^,���d?!4ձlö8:�q�;�M�s�kC�$֑��Z����%&����:a����Ah��*��0�D��п7"��G#���r(,����j�3}���>���DZK�n���u9���rl*���Jv�_O��[���?��n>�P�u��`Z����DwYtc��j(0̹u��:_�=�p���b����Mv�u�G.~E��9��t"C='3�O���mPk3Ŷ�m������ J����Y*-��3C=2<_@;�M
wh�{EZ���i �!\b��0b��U"h�d�Ns���P�1%��}��b˒��V!�Tၫ%�ᄿj~�k�?ۜ�G��*;5	�O����*�x6i�:*��-7_E����KM�)x�%q��}4����EU!�ϤC�-����
���{��c�j~�k��Q�l5c���p8��+����l?6i��f7�-�H럽��;PV"���k`{ɮp�H�u9�i!i22�\��o?����Y^��:3��G���p8�n!��;zc�^��Ϧ�{����P�^�7���<^��:@�#�t�m��[�����@ŗ�A��H���x>H�.��۪1	q^m�������3��W��\�i
��Kf!]h�#�t���)�����qR�� �F1t�=�e4���_Ȓ5�9���s��6E��0^T�z������Lc�e���h�4�/��ڈ��vξ�?5!_ey�߮��?* �?�Kk�ډ�2��v/���Z+�v�hv�hv�0�
,��6�0D�g)��o�1�}�o
��Z*�iE�G|�C�6_�v�{_u
�\Py\Py\Py\Py\Py\PSl
PSmJ�H��+s��)�i���8�9�M��1��L{7]�d�Ku��o)ɞi���8�,�k�<j�Hd8k��j+�*<�(<�(<�(<�(<�(<�(mvJ�r�ܯ������N/

��]�������J�6�.�G���JN�
PV	���q �.%��{�f�Gw�>�FeG�q(�.%�ģи�a�x�=2�k����Cи�c�bl�c���xN�!�?��;������l���6:���O@"��^=�����l��1��0�F��]E��\H)�B�4EP�ֆ��lY�O�M
q!ȕ�� �p>b�K�A��y1ZjvHΛ�є�zrs�k�cǰN���H��U:��,�;�rÐ��F�E�j��!�WD��6x��9�9��اí���狕�Oѕn
2���~Q�o�s���u�s#�S�|����3�sY\�L3�K=^��&��p03N�6SޯO����z�?�i}�������5;#�G��z��@��2�LX��u��2�K�|Y
�I/;��B�Q�fE�\��Ul���/U��,�{h�S($�HA�{�����r�s� �����9�Z�}X��wL@�o�<[�6�c5�vA��寭wV�V�%�i�"�ں�47U��c�Ȳ�<�}�8�V�s�E��"�4�l�ip�p�o�J�2�ՋXd�]�qb�gmF�5������U4����3�5y�=C�J�W��6P��J1��4�Y������.�l�e�4��.�CW��=���6������
u��_y�+�3�6.�i1qE���gU��ʹ�Gn�w�aK����k;�����9:��w3#VRa�3���"5\,�kY��Y��#a�Z����HCkT`�j%�;�:�ʹ��i�mly˩�YsA��u����v�f���q��u��Y��^!ޱ�:���Z��^!>��6��:Mxfu�ܭĘq���O�k�H��"�b�\,��Q%L���}�-l����5�"j%e�N2K<s�GgŘ����~�7e.���ITs*8��&���#���l~��26&2��@�炍IX�8�+�1�^s�0���q�hݭ�������+��!�@��O�ۯ�mo�'��mW�t������D�K���@�k���!�S��˘�"�>�;�!��G�$M8��K�#>V-�Rγ���F�����c��U��L�9�32���#���୵�-�9L�F�4_���iH̙��:�X�f�����k,�������B[(Kb׹�$���VB�Yk�l)A8@��B,G"b@CɌ���Q��1�t�<N������1�n�����}NK;.��l���毷�)rf�<c�<��ܟ��YSjd�Ev�H��GRH��IyI#�m4�h��9:HuTPMR�h�A̰Ө��9R����F-QA*L\t��FRH��IyI#�)$q�$�<��ǔ�8�?ͧ��z����ȍd�`��nD��� !��<G$�x�A�M�4%PF�td��UV"��� ~r��_�ڇ�y�:[IV ��ȓ�t�5Īh<I��&�ĚLj��l="8��G؝-d�#Վ��W�{#����;��;��;��[Q�ro�cQ������t��՝�&�-L�d���-�|����
e^$8De�_�6�j�PYH~ƶ���J��瞹��y5JH����u��K���M�ֆZ���E�q`�C��I�ټ�\݌���M
cq̆�y�}5kp�c�P[A#ɨq�Do�v1Ԇ���J�UD���_��K�BWؤ��Y`^�*sj��m0����m(y�v��(f��g�(����:���}���Z�� \����6��9���6?�6�|~���aC�TR6��0'K;�N;��Xt���"'{B�2c�&J���V��Rj��[�pwXVY$���QNi��]����3�p��/'�-_J����[p��%1F����TP��I�1�bC�C�K�<�`Ty4�L��,0M$�IP�'䶭�Ŧ���ͫM$ة~L��,��y8��W|IS��9�M�����̇���4B�k����=�Y2�.b
4&����^����w��y5�h����
��a�C�6jG=%>��,��D��9%;�G����eԺ���sŽ��1����X�h�߿�m u96����aKb�t.��vN��|�X��y�as��R���n�f\���AV�y̐U���gٖ�����:K<�v��^p�3BI�ê=y�����������f�n�[e������mi��:#��s�'�:?e��UAYU[!5$�����(��.a����`���v�W��3�Q��l3�9�퇁X=\�w+"��+yw�ٔ�.�e�y�J��V��6�\º�؄c%��X���+�W=��qK�3?^�Vo���F
!1"2AQa���0@bq��� #$3Rr����5BCSp%6�����?�60�"v�Hiqԝk>L\DZ�-�vD\�Cv)x�&.'��c�G��JdXm����,��f,Ŧ�k��0�1M-nŦ�`N���L
�Y�5	�́g,՚�&'���$+1f,Ř�PZ���l�%�n҃����+#ڟP\�b�Y�� �3S	5��F�#��b�Y�16b�v��g�*=$��;Sg ��G�ឹ����+1f,Ř�k�85CN#�v�������g4,՚�Vj*k��մ(�l���\4��DdBEoS�yT�6(�ܪn�V���j�Y�5R�,�iLcX0o����o��՜��VwJ�mꎑ⦵�nK,Q��T�Ȧ:P=El��;�3E(���9�{tJ�Ѿ��*�Y�9f��mv5l�4T�C�5��-L<(�C�;I��V�A�Y�[��o<���&�c�Z�)'1�Q2J��mP��co'��r��a��զV�Ze3I���3p����MEOJ8_?�����n2W*;�����U7{Q�X������ā�я�N���gB�����������%M�C�!q���_�i�X���
�P�����Cx�·�޿Gr�lj<�����w��t8c��j��C+\�`z=��؏�]������v���ܳ��wo�[����v��Ow�R;�� ��7I@y�ި�髛�g���d����O`%n�(��tc��>��N#{z]��l~C�����_�1������g]M;�������Ww��p����?UIu�������En�:�},���GXU�/����)w��� x#b��f�Z�?���_�>û;�u|T����EI^�@��������t��y�������t�e}i�����Q�V��1
$N�c>6������5]+]]>a-���p�G�Si�\�ks����OVf���~��.���*ӦnQhm���&�����n���z�ǥU��o���'��XV��0���j�r��5�nU���z���U
e{�P=��Z���PU��p�������;u�
N���+e\�j�ɇ��SڭWs�ӯ���L��`��u���/u����:���)��W�$_8��QR�,-2��o�[.�_��4H��V�-�����~�w9hÌzª�/�X#G䆵�#}�S����B�'���U�4w�Jvs�n���Z��6;����ڭ���|������	i���Ƃ�%���G�{���ߛ�{���ߛ�{�����?��+�E-EW��
zU��)�'��v�*�	e.��T�Ju�ȯ4QF[Qտ��Zg�������+|�k��'�o����G�o������(�`��h$���CMOO�mȮV�뙈��~�QO4?Q,���Hݥ]��*VPFz]��Ȭ�M�c4�Fk*�FئG�~��em+�$=-���S@�d,vиK*zy��1��V�dt,��w?w�IO��R��0�(�awZ5�B?��Q������&mT��k�v������u���b�ѸP���F����Q���6����v��a?wڅp?Џ��U+�R��>�<�X�<�ku,��p־��[Ɗ��ئͫ���*�J�.P��g�a�|E̡�R��&�~WYO5N
iԡ�@����jQZ�+6�:y�k�yus�T/�:ˎŽ\㋊ޮiť
�\�Jh#�a��:	!1AQ�"0@aq�� #2R���%35CpB��?�Ȫ����X��'��Vz�l�`��j�ۓdC*ޏ
5�w��G/���s�3��*���HܭOB�G/g���{�_LЬ]����*��H�F�/(ۍ1���>M��g��V3؟wb�<�d����?42�&����$��Z_���O�߰L�7�cؼ��Z��}�/[}#x�?p�_�n=ќ�DZ�د�5�ǵ�Z��kO9<[���7G���
��-?J�I�Xߊ�������!��5�/����^��d��ZM�ۤ�\8��b��RWk�Z��<��|��ݵ�ұ���X2V���)-~�v�`�w,{�a�)>V!X�5�7�r}�����|�b��Z����L��?��f�,����X��F�hiv��1ýi�5j
�FOzk�^����m���t�vZ@F���Sԫ�f��P~V�س��<1���7!j~O>/��˻�� ��mN�lG�ګ׊(�X�b�R�Z��-J�R�c���$�-3��ˉ,����!��` }�r܌�W5*��C����67�>������|�X�s!o[���;jzT��N����}yLn��3b�ǴaG(’Q����op�PB���̭3J������z޷��R��*����Ka��9>�K�6��t��]"��j��k
��I�t���j(����0��灻gb�Z�v큊X����2��F���Zf��-��Ą��]"�J�YwS���nz��*���?�M�
��L�e�W���>��tOj�a�F�
�2⤑Ҽ��F�\@7��Be�.�:�
Ư83�S۞�󏥎'Jx.�'xQ�n/��]tsx��A׏�c��f��>����ς5dy�B�rw�^GT�k�<��.�����j��d�w����>u��>|�ߜ|�)"�(󜺜��I�<}({�"�`�qF�#�.��S$->i]i�N~�Ħ�i�J|���[۳iQ������Yo�׀W��Xn���������を�J�'IQ���Zr��Y–Û!Caϔ�����9���{�Sw�u��?d9QX̭
i�y��
�Ka��TV�TR>N8�馦��j����IV	��P�_(��*J�Y�TpAW�Q9�Y�{��a�����������]X�m�U��Ҧ�9ǜ����L	0�
63��C��b�ܺw.��˪���.��p��H�]��@���;�H�Xԡ��<y(�ې���O��nJ�	��S�����UGHO0�Dap�x�F׷!up��dq�%M/Hxr�F�#?	U�l�k��}�Q����i����Sad1�*������i�l��S�d�㰦顃��Q���;�Velgk�}��H��}^�an֕���-ܺz�1T�����+u��Q�r��{�ֶ����ݮ>��۫O.x%�{�U����W�t�]^a�9-J�K�s��&�}ٰ�ϗ�yIC�ņ�\�޽Z�q�_�uj�Gy�Qմ���#Z�i���&��t&g�8�/)j�l"f�;8���;�(�1r���̧���a		�!123AQa"Bq����#6Rb����45@CP����� $7EScrsu�����%0DF��t��T�������?����P�ӥ�K�|V�(Wǎ��U	�`�5�T�I*��`�
�0��M-ҫ*{��5����ł�K��;a+��Vڪ��~ސ8@�'$�ш`�7�D���-̎�pQɮ���-x��(z�1�"���3p
���G������*�&��>�4��ӓ���ª��h��@��T���S�7Gi��7�"N�λ�����s{���Cču�&9��s�����'2h���7�~����ạQ�Tk����.5�RENއ~^~<p��)�z;��A�?�c��Q3�B����
R�f1�+G;�7��T��V�_�1ۋ���P����̊����;�
���9d��mۤ$������O�A�������'2h���7�U���ZFr�2�631�~�,>�0��h�.b��Xd�P�%�>����uE&�\����Q�b��4g�hTJ9�C
���L��Vj3�׾j��/|���.1�L���fa�`�	���Ŋ3�����.x_���V�4_�����ɢw��߅�H�ZFr�3��2�@�7�	YG@ǯ>dz���,"�Yi�R��r���	Him�Y6�DMR��y�d48R��B���5��v�e�����p�[(����2�!v�V�	L��m�/��a�#�c9i�H�ZD��<*�ԭ~h�oH�Q;��D�	�
��Fr�3������g- �z()1|8N�}�n��|�Z�5��L����Cr�#����s�35I�Uq(��B`�����Rh�>��:�8C� �3��-��K>��o{/�F	6�I���D��H��h���r�3������g-"E�K��A�������'2h���7�~�2�#9i�H�Z�r�3���)P=�v��z�K�F�lQ뒊L�f!v����bh�ۀ`��&,�qV������������
yS1,�qViz��P�8��@Rj_42L@F�S�I���$�>1�S��PN���=j*:�5z#9i�H�Z�r�3���i,:\��H?R������B�{k�j�'_|tġ���/��B���Gnb�c.���	3�Lp���U%�˴��g-c;k�X��@����0Tb�������n�Mv,o���ǂ;1qAh�e�Q4����7�6(^m��	M���r�r�$�'�)��f�M[ [�WX��C� �$���B�_�a�
�����~r9p#vo����A��\p	� R�*)J|����g-c9k�H�ZA擉�m�O)E��;"_ ��W+

���s烠7�Ψ�H�Fr�P8����?���)u˒��&oVO�Hl<�J���Bm�
"��R�����	/~m�0��*>���㌻H�Z�v�3������gmb�j�&襩��~M�l�"��ps,YM�D͜L��4�J��i�KZ�������v�-^�L�n���Z�
�����\n���o,EM�p��~ ��"�)H�ũg������gmc;k�X���r�2� ��i�|�0^�W��>��sA'��gi+�޻pZ�Ԋ|.?�磒���.�}����
���!IR�`��0`�'����������Tv~,y��֗di[����Ƕ���lG/� �i+�U
U��%6�
�gmc;k�X���v�3��vO�MdT-J$���`��v4x����j��}Hu�lcŏ�	E�,���7�*
�*^�.�#���T�-�j&j�`�z��$�n�UCTR��=�H�7�ͅ:��H�8yLz���C�c]�EꃭCh��Ŋ͉E�Ri$k��6Q����gmc;k�X�����פJ5��1��#�{ʝ%p^��r�9����a)�d#'3|������
�	�@)J��Ś?y/EU�^��c�|�����U���q����gm�;m�oDgm�������	Z��z�1��p�|�$O3KvJNz�!ԭ#��$~��z�F& *>�f�Q?�/t��K0�-m�%�U��V���0OrJ�z�!E=B��c��p�˗�o�(8Ca���v�3�����Fv�3�ѝ���3���}_��|:��H��e/I%���t�	Q�5��Y�N�矘���U���q���Fz���oDg�����Fz���oDg������'
�p��I��֡�L;MW��( ~ޏ\�Q
0��)K�QS{��o�Ǜ�]p{�NsT�F�ݎE'��z��‚��0y��id�����F*�v��������Ct۠�oL��lg�c=m����3�ވ�[z#=m����3�ވ���!����D�u�ڱ!��:�矘���~S�W8�Z�v���oDgm����Fv���oDgm����Fv���X<�Tt�L����1�A��TՒ�%��ACVt��#�����QY��9`���/~�ZAI&I�h�o�Py�X�H�ʎ�!�����@�V'?�GK�)���la�%��9K�1���l`�=�G�ZTwi@u��)������*AF�I�h�oLy�P��sN�\ԍ���c:�ޔ�F
E(s5YJ͔�3�e�,}�c2:o&��$>U�h���v���oDgm����Fv���oDgm����Fv���_D6�~O�_���)��qF�E�r�j�%yF)��^[��zK%.�(z�@���q��fR��AL�Z���g-}���Fv���oDgm����Fv���oDgm�����O��t�5�� �(���@�
��|�Xj/z�1�qqBR:C{�N&cv���y��UT�R�+1�qC"\Ĕ�9��H2�6����|��D;r�}���F����v�=O� Si\�Hu����W1�.�Pv�$�˴4��Se00�UdTf�3�)M�[��!�|�=xS�¥n|�U�&/z�1�qq�K$MH�A�r������gm����Fv���oDgm����Fv���_Dg-}���L��7A<�[�d7��NL�r�2F�L��J%
GoI���*r٧o-y'0��9+���C-�tRԌ���d�xA�aI�����߻lZ�%��|?�M��{��r���A�M��y�.�3�����寢3����Z�#9k�寢3������#;k�X4ڈ
M�3[��W��n,p7��W�" K��l�B�@tBs�94I�UrD��l�fh�unxR�H@5�u
R�_�
ɮ��U_�u��X���#;k�XN���/X.�w�g���x���[����ōE�\��'��h�F�e*���X�ؽ���� �������#���I��eouZIq���ǎ3������gmc9k�寢3����Z�r�3������H;	0���`�+ړ�x������;9]{�nIQnu"��>x���mnLZ�~��e9t���!!��RsA���`8E��� �����S�R�l\	���:�SHl�PIܝs�G��
ɊmC�X�Z�r�3������g-c9k�X�Z�r�7�����T�\CW6(�n��/���Zz�8#��0V pa6��z��ژ�ß�3:y%�'|��"T)�����}=q����g-c9kQTՅ�>��*��S$ӥ/��<��	���x��mPx<X���M1��(���
�H;ԉ��1��!lg�J�W�j���X�Z�r�3������g-c9k�X�Z�r�u:\��5�J����-0j/B%+���(���UM[0%9����bA!/����1�E�B�@�,�1�UH�-bA��0j�_�T�U�3������g-c9k�X�Z�r�3������g- ͜��&rܜ�5``�1/�Q5jg:�!̜�\$��`߸h���X�&�V�]�*��bt���C���+T�s�̀O�1��6ی�H˴��H˴��=�ժ�೐�L2@x͇�"Q%v�Ã!rQ�Pn�*�9"a4o�l�UI^��F&�Te��PSQL�|'דn��!j!j���3������g-c9k�X�Z�r�3������g-!-��$�U��Q@�2�\U1KP�o�
�^s�H��_��~le�F]�g-#9iv��iv�����e�Fr�2�!I����D�R���Ch)CH�oE�����1��C��Py�`M�bܦ�`B��*���5E:��@ǒ?�n�4���^��)�d��&n*��uA,��X��Uj�ɏ��V��il�����#D���u�<,,j���v�^��~�P� a��V.�4Έ�z�
r���v��Z^赦�FM@�%��C�So
��|�@p�<���"�0�dͤ�
v�����g-#9i�H�ZFr�3������H�ZB[��i�ė����<���x���}^��WN2�#.�2�#.�2�#.�2�#.�2�#.�;�9L�B��(n���/�	�Jښ�ƛD����֠F�Q�@�tC��6�t���4��9�����DZ�L>2����'�}I�d�.���H�"	�F��t�G*�4�����	�Ѹ*���>(ܣ=�8�B�q0�	�>梮
&wR?��R~�T��I�k/�u
� �����BB���Gպ�+�ﰵ���f��&m(����9☒x���Tm�8S�I	�>ǨɛIL2�#.�2�#.�2�#.�2�#.�2�#.�2�p�‰�"K����{����b$���1�k������(�Z�:�Q�����Ƙ7s���"d?)9�l�dY%Zj���L�B2�q�ӌ�Hʴ��Hʴ��Hʴ��HZA6
�Zj]aH�]���>�9X�XJA�&ʱ��AWAB��-�Q�5��tRv�h�N�8��8m�t���E�k�MQn���U^��c+�}8���WNv?��Z���VC���� ���ҊIIڛ'�8�O�8��r�R��e(s�@Pb0��W^�6TA�x
=��
�F��ԚA�=���c.�2�#*�2�#*�2�#*�2�q�Ӄ�~�4QL+QUV���FƇ6����T*�����O�U��MY=���K��҆4NVcH\��q�&1�}�w͙��06�Ā0�D�<ö2�,��h�E�֢�'���1�
�Z�pn���NZ�l�'dY%Zj���L�B2�q�ӌ��et�+�]8���WN7C&��"��Y�Ґ���<c�GLU1L�YR�����_7�W���#k\�T���P»|b^2�X��6r"�\�j1��Cr��let�+��e.D�S�)�(b�6/���<kT�j�
e8an���Ǔ�b*��1����9�7-\�-q|xR�h�g��5&�y#+�]8���WN2�q�ӌ��et��_�MS-j*��R�6������1p7J�%@��6�&���m-]&���D��4�+���f^���v>(|b/8��Z�}��b�F�Te��(�${E;�t��|ڌO%/͇u1h����P��Nz�P�aIB��C�&��l�v�]��?�(��
^1����N;�W�_Gë�/�������p�����u|�ӎ����p�������G!RT�p����8b8oB���M%3�����U�o�;f���w��R=���:_ԏ_��r��������rɽ0� �
��Nֹ7��L�H<Ci�Nց7��P�Dc��eD\�B�;f�����o����G�s�'K��������:BQ*����V��uK��l���>�����.�/f���kLw
����;�W�_Gë� ��w����;�W�_Gë�/�������p���?�,���.!�λ����(W�"��|������H<`
����E�Y�p��(��T�=���:_Ԅ��ܹUMr��)�0�/�W��&٫b]��������r��q��.�6������:L���ȱ��;��÷�=ǧ�������^�w ��+֎���z�Qhzc��W����[�������Gr	�Z�h�A?+W��'�j�����^�]%@�
{�n�]-@�
{�n�w��+֎����z�Rt,��t�Z
8��Qj�j,ܪ�����0����͜���'�&=EA]
l
��Ǩ��7R�qĩ�OYWWJ�C@x��gt�Q���� u�K�z2D0�?��t,��t�Z.T���.��Ee���+u��`���7�����?�����?����rz@B�n�wP�Z;��p�Z;��p�Z;��p�Z.T��(�Ku����^�w��+֎����z�~�ɖ\� ���1�[`�X�v�C�d�NVb��;f��<2}@tB3���4pK�WHp=��SF�2�S]5�11�R�/��%r�܋�t.�Z���n�j���y�~�8�O�1I$�`ɜ����L=��WJ2�p��{2+I{B�9r����;!IgcF�*fP<T�w+mÀ�A�T�-+zSa���Ţ
������f�9�o�W�A$��O�j��E�$� RV���P��
�JR�E�E!t���<��R	�r
ʓ�D��$AѴ|Z`^4If :Z_�a��Ѐr�gH��^
�}��"�ф���E��ޣ9l[�	�*]��zX�+(��5�I\�)��N�����'��T9�ҩʯWJx)���z(��1���	d��%)
�qiP��MЮY.8	�p�����ZG�4�WJ(�F~�v���f㜹��决ZW4Q�W���q�qrA���	e"�&���n�i
�H��b�;���X�(���sD��sT?$���ъ!Xp�Gu3���~iK�Yg���GE����?���d&D
Bn�����ŏ��g?�;���X�(NiM9]�MU!v'�ܗf*댾�et���Bъ�,��\�s�Nr�0w�ɲ�z�xNU7�MαM�:�e�_˰�p�JYI�2.tw���)����pWV�uMp�_O�ӌ���F�����7�RuoE!?�8�s��8�N�D���b����q��ѣm٦j�ʵ|�yE&d�ɚ�����!�;a� �<���d��~�P�{פ�Af�k���V�#W�����a.�rUĊ8H���)��B<ZG�l#���+���S+W$���5���M7��&�)CPA��T�p�D���
��5��!�&��a�8�'�^�"��'K��K�ʕ0e%ɂ��QG���q��z5��M��$�4vn��:���Hm
�8a���I�*��¡��v��_N(��|��1MP������EA17��lG�����[|�b�$�ؐ�����G�#���ӑ8ܞ����H]��|*��T�5�G�#��؏�?��:Պ��_N2�q*
��������*I�W\T��|�P��cH�VG�VnsY�Hr��=�4�����=�R*<���(�-��	�TƬ!�]8{8(�,��]���bJ�b��8R�$)��Kp��Na����_N)'ܭ��� �6?a�JaE��r�D9D�bjks=3r������@Jٖ�id��Pe��/�(�����X�j�bF)����=Z@��?,H��&������t�D��ӌ��e��~���H��ym?�$et�+���[|�b���N��x�ӄ����F��@�Y���c���Ƿ�<ڗ�oy�/��4�j_�%4���3=p��*�I�w@UF_N2�p�iG���dJX�_[62�T�{i����8�Vy�QnC�$�!ew
�J�
��s$�"d��ճ�������.@*Q1�&`�!��K�R��t��-��
�o�tܓ��e0��9�FWJ2�p�N���j���(�J�N{H6~-��{��i��*��F����}8������T���B�e��f��ҕ�xa-���5s�6�aJl.��S�_��9r�MfM�Ṯ�#/�}8}K�)R�j,ac��x�bN5`Aл\�����X�8��nG����C��$���e��/�S�>RF?��i��#/�}8�J��Ko�u�����%��~�1#A�E9
:LC�`!w
"I��� q'��=����=�����I��Y��)K�]8���WJ��n�����EL<gs쀙�\iRG�t�
��	��o��6�r;�E�
j(;�8D�����*��T�%�L�
K{��:g���Q�!��M�耢ݔ�T�&kߪA�u*_��
0G��T�-�j��e0k����1F����*Q��L_���4��8�#��^�0��C�\�Z:l@M���
1]C�x���K�����<)�0g�ړ�mr"�(���
e�b�l��yZ[�a�:�:a"
�>蛬C`j�
��8��_&r����Ʉ˷G
b_��=cS���q3Gi�gdaǃIT�-<g2@�*6x^p���Rr�K�����0�`�6���2TT�QE0(�M�]A�i�+��r�4
�͛cè�հ6���}Ɲ�e�'��3���S-�p�vro;'�ɼ�Ym#��XrPo2!�n �)�G�)#���L��ӌ��?��m�%�7��:Ӆ�FWN�h?��:v��$��1:���.�‹�I�:�!��wg&�qݜ����^6z��"]��9CEa]8;ǎ��I��ETV��5�聢���T�(kߪK�u$_��
0Z[�|�1�5���R�G
k�>1�	���MR-�I$K��5����[�jRT��a�s�Rg-Eyb�o'n�jf�� 1�$/{i��T�*�j� 謉Eb\.�m�.�<ױ��&f8�iL��r_�S��"P���9L�>#@vѬ���ݖ��%c����j�.V�.Z���/9�7N�unL\Cu�Q��I&j
�Ș�r�mx3c��>�;���;!�y�y���x���q0xB�s��A'�w�����G{Sf��9c�`W]k�p��J��T�L���r8r�`
�+�̷�E�̳�E�̳�E�]+�>��͒�2�+�sf\�$oD���K�s�H��w�Z��(-�J7��(�ị�	JG�2�q�Ӈ��n.� ��
jʘk�L�uHe�JPn���e�)j�Let�%VR��
��¨9Ȍ�@N"�pDZ�q,{[�DZ�q,�R3 d��
׻(��y#vO�vӇhh��U^ մpG�V���3���7Cj���WH%�f�Z��,L!���w)$�2ĝ�X7�Z��;`)�b'nܠ���G��UgϬ>�	�*QU�j�Ǿ����׊��XH)׊Ŝ���׏aJ���x����׏aJ���x����׍�Y`q �^�����R�Ձ�T�����]8���fRR������-Y��A�@1��k7���n��	 Q(��X���բ2�q�ӇSz&��o���&�2�*�VJ�æ3���Ű��#YJ�C�Dq>0���et��5�(�P��X�Ͼ&���\�c�R�'?^=�*�s���R�'?^=�*�s���R�'?^=�*�s���R�'?^=�*�s���
2��B��BV��[�g�q۶�*k�Aa���y�����vX�F���KPzGo�26�(�e��[�w�X.nn�.��N䝒K�nif����9���<�����5�,}���K|0�_���<�����5�,}���K
K[=�NV�˻����*À8���B󙛛�v�
���@B���C��=��f�R.B<�n�c+�](��FWJ�I�����L�QL������a��X����@�F��?�2�p����̺
ݶwqwq�X0m���k�X�����>�a濥��y��c�k�X�����>�a濥���}�K�Y�\��v�}<h��X���*�uus�U|��Gi$��Z��Ѵ@������*\�"���T��TO�Cg���n%@�Ͽ@��5�FWJ2�q�ӌ��et�/�]8��B}�%��-��!cdO�_�	��_>�w��/zN@�FWJ�%�1��'�@័9� �_8�-�7G�r�����B�h���5�άf���XS���}����:���q�Ҍ��e��+�]8���WJ2�Q��[�OX4hC��7�
c��i���Е z�pP�$_�$����B�Q�y[�@���:L#�G_����r��.VE@�!��5ڊʌ��N+����HmӰcu�=��A�[#)�Lu��팮�et�+�]8���WN�'f
e��Wy�G$�]0y��oȵWu�9��A�^Q��Q���u�)B��s)Pk�+ �Z���0�c^W)�UQLK-p{�L��������+���9@�9T��2�PJA!5�j�*ޕ���<FmH��
er� >iP�/�@�et�+�]8���WJ2�Q����P���T�(:�l��j%**�*�0]{�!�n����Llչ.QE0��2ҙ�4�6pA"ȪZ�p����I�tα2elś�!��/�v�a4��n�yŗ�	
^1Ž(ʬ�ލR��1y 5m�2ֿ�׭�5���h����6�G��~1�ZB��Q6�"�i�nP�t�>FT���W�>0�G T�錮��K���ĵ��!
_�88��zT�:��3U�*������N�̮�R��d+ŀx���6b���6-
_�88�5FWN��s����L'�����-z!t(�4�p *&���
�N��k��cn�{^��u��濾ۭ%�}�ZqI�d�5I���(�ն0���9@�7�	�m����:�T���Q
^v��#)��M�f�E"�R�.$s��]���5�7�M{L9h��ܥ��8_��MM���b+���U����V��_N2�q�ӌ��/9�8�A�B�����y�`G
ߝTl�r�@x�(m#f�R&�@�!MPD��)�r�NC�0j�^]X���敛:��"<U�v�7�K\]�� :cw�u팾�e��/�]8�OӃɨH���FwuZ)qw��NJ=z�S~�E�
r����~��C$fV��A"pC��gtr�+��9K�\�P�>s�Q
u+]Fe�ASb'|��l����>%>�{[8�����l��S�ǵ���O��h�.�mwv�t��!�pi�T���0�W�BB�I�Gh��g- ^1N�����k	�'�
����4]�����LG(7�4�׮=��|J}x��q�)�����ħ׏kg�^�PYZ�>R	;又f.8NyI/sI�a�����8��o�=L�26���\�܎���*^V�^;�K����p�yZ�xyJ�T% A�WB�j�m
�1�!s-M	c5�����]�Y
�iNj8�ZB�ي��K� +�Ch(`�Oe��U
�b�Ϥ��3���#i."�Nj_79���Y���XƬPҕ�(JB���݋V��D�0�*^V�^;�K����p�yZ�x�2�H۱DF�Ut:�q�/¨v-�f[2sp���Y�!�&��oG؜�Z�T�ꃔo���.��4}AQ�K�-�ʈ�|�ճ���3�����+���j��r@����R��!�K�Ժ�S>��d8�oL��x��a0�P_���*�����٭��E�ܯڴD0רnM��;����?���c2h�RޖUyP$�]\8^�<.�h��}�C|<��od!L��x봻�}�z<�
�gl ��L1D/h���V��us�;e���MՆĘP�(+P&w�ḰJ�GV������[�c�
2�["0�V�)���r|/ La�j�7J���|f7(����B��U�|�c)��{ضzk�^(a@�ے`1y@:���[0��bG8|E/(���4�K�ȱ�
r�� H#9k�Xc�D���T�e
9	����aKXTv�
�ͩ����cزJaR�b����6��_�6�"r�$J�9O���0���T`0�da5�9���kU>�s ᄣ�݋'f�A��B)�\�NP��GT��ĥ���S$�p�UQt� e.a�]x�9�]䕹��G��J�k�Pt�U��Ów��<_�۟�AQ �B	�G}/[K8.kT8\u�C:sC[����5�����VP<:��*���PP��hԎaDH.R�b��Ț��%��UEQE��R��l�S)�;j�����FS/N��tqP��s23izw�
��嫛)ض�&��\�pl��&c�v����#l�����7D=�F��L��Q��ɴ�o�;lj��<;�5|�㌻H˴�L�Q�#�i��<;�5|�!��w�\���9���ۆ�#���W����[��pP���MM�c/<�n�����V3sG��NP��˓p�N|k�#V������h��q���F0��]˨�.A����(��A��+!1AQ�aq�����P�� @�0���?!��7���
��F,��rb���'�}�L����A��vu��FD�5�h�'Q���jx�Id�6�^fuHϲ���mQ�J��17��s�5�/���T8�6�
|5�	��6�����Y�����{�m+�/��L�q�RyH�iڍ!�=������!T��{،WB��9��b��1�O`@��ja��.�\�ږ�#�����ʷʛ��F4������
\W�w�f�H�q=��:)����\�*�O��h"SG�$l��բ״n�7ʦ�_�ߦ}��qq�W�����0�
0���ahL�tsX�9���o<��������4v���1H��c8ic�@�i�T����-�Rq�W��x|�Q����+q��\W�A�Ҕy�Sq�Pw��N�wr�+A��wU��q�j����=@O���΁����%�@�ۃ�j��7��o�i �'��y�T��+���?��^��#����ǟ�8��?�ҡ��O��R��:�p��T1H336�v����
��^�d>��%���f�*�����`!�:&�ܵ�X
~?J���-��\>4��ʤ�/�u���H[Py�EY=�|��/�T�� nbɨ�֊��T\=)�/J���A�Ҧq��s�Y.W[[poj�bl�/TǿEt$��iP]��j{.�����}��4i�X<  �b�q�8zW���H�����P y���h.�V&k؅j�\3b+Q|��J�68~h�ދ��׍OM��������t�7?�L��P���_
���L��\W�Y�N���݅3QvX��f6�W���A��h���g�&:��)9�l�kv�kK�n�Lg�X�^�/ju�ʙ���_
���2�
T��������2=k#��QS+7����M�
�G�]� ��dG%^�,��'I�ʖ��$�'uK�@ir����#S8�Tx�Ty�Q~�?J�������58K���e���Ћ���
��pG��/(�u���bQwC�j3��{��]CHB
@*W?*���L��Ty�Ty�T�>U1a=0RH
�-\�N��I.J���Lpvu�F8 O��q^��A��r�[W1���^U��\~DR�q�Rp�TG�bA�ka���BBk�a�T��[n�[�f(�&?��1
���pN���L���Rs��X��~��~��?
��?
/�;�ʹJ=�UF0��?���,U�+��DD����A]�x�ZCA	�K/�R�nD1�9���졀(��TQoWn���qP��#�τD�%"��3�k���?�+Ao��,)B�E���vV8�(�.�A�?�%Q
�Te�ʊ���v�u.�dAi���W5<cʿA�I/��6���m�1S�v(^�)�d�����_��zb��P��T�Մu&媄�`H�\+���Սsr>���_�2��/����*#R_�B5�>���/�ؗ��5P�%����D���sMF��\v��X�K23�J9�Rp7q�r{Y�%�瀽g�A�ޅh����w6�6$UЩA��?��βlȃ��5�ة����3r �vM$�*TDl��43��̄�:���:�?}�Ԑ �H9����,��؀�U�ʒ��򙙈+�P���@�&<t-u�]Ҍ1�@`��^�Z	C���yS2~�?+�ɛFj�GDL5&A6Z�h"V?��Ȣ9қ�Ҭ���Y�����f\|�E<v���(�=]�u�R�#.���]����N��j�5����@�F-��e:�~��?jq8~��@�R</��u<��%�qB�m$Z5�Tb�y�c%������Dlp�\��>���P�f�hs��?���7'�:y�WdM��h�]�
͆�H��C@f�������4�f���Yy���������6*D�%$��Q<<�����������J�?j�?j�?j�қ�җ�ҁ,Ј�N�[X�;Vb	]�k�RY!����XjE���;
�?u�F�S��Jy�T���J?U'�F�S�;-�Dl4c��>'�^�t���KL�RP1�]7D
����~����_��_��_��_��s�W��W��R�<��J�B��Y�WI"`v������������8 �MuA�rR[E��g�tѿ*���y{W<//j�j炥��R���y{S�(?*l�$"iV���eӍְ �l����X�(��:V��JYx�����1��N��/Yt�K��P�}AE
�
��ʸ�@�o�j���Sq�!��L���^�//j�/j���_��K�ڥ��\�P�����ʧWr�����2@%��z�vv�tR�?*T��x�Tq�j~������C�ڡ��\~5/Je9�����tc�
�(9�y�1��)!�W���(5�#�
�@��K�v&��t;�o��{!.kگۗ�C;�F���m``��IQ���� s�/]|�,��Y��xe4�"��㨒"���UJ�?�C�ڡ��Q���x�T<}�>����S��[������X��(���R�*Q�ҹ�k�ƹ�k�ƹ�k�ƹ�jg��e^�y�b��+�s�	Y��'V�/�c�y�|�D�kGf�y�Q:����Y$FQ���7�p��(p������x�	�ozN�Ylv4D(�Yh�|�M7N[C���?�g��J�(��^��U:���"�6BN���-�>U��\�5��\�5��\�5>~�'��#�ҞN��_�`�vĀ�sdk�5�u��-�6�l8�fe���P�4�v�s��9�S��W�O��O��O��O��4���.�'�Ue�`��V�8nr!��04�dM~�$(߱�IH�����E9yP�~T���()�ʟ���3E���<hF_�K��:����$.�%��`܀��|����@X
i��S��S��S��S��\~s��~��y�]H������#�s�W��*-m��76�MW���		Y�=Pv��% ��.�p�Ҷdl	�3.�%����`N�E�җ�ڥ�ڥ�ڸ�+�¸��F��ϛ�]
�Q��wCw!��o�k?OUs��)���!	��軴�^��^����Ԟ���;%7���t�d~�w�WMA�D�uR5�Vx������\_��*\��\���¸�j�*�U�`����1x�A��^0w�1m��'S��	Z����C��!��3/����oNt'DWT�4�H��P:=ϧχ����}>�|�GKw�Rq�����2�U;�I2~�N���\!�d����kZf�[%����Ok]�K�����>R�"�YK�:vy���
PA�=.�\`t�vە=��>O�������YD��+=<J~z���%e��^����us3��^„I�.Výc6�z�٤��wI-x�A����
i�����6��h�)I�8R�Q������KN��,eG����AXfuB�XU�lp���a����{Z�vrG�����Z.
��f@�����(��c���ga[�����[���n��K[���*3C^���>lIޯ`�sC�0����	mx���A��FDn"7����V���&i����U�5�>}�)�,Fר^~T���X�`��l�
rF)[����^s�(<�Q�ڐ6�Tl��p_3���8��a#�u�
W��%>���<
��j��GL噃{��@�t�"�AC����h��]z�%<k��$Wa\�h
�_|b;"��!������ji*2d ��*�ZZ��F�Cht`׃@C%�:��o3�� �41TD��~��6l����	���O*���V�E4A<E���F�C�R.�Mr
>��wދ[���]��S��H�}s�K��0`�K��#��m��m�b�����B�Bv��c�Բ>��T�1SU/�[�"�^�I�HZ�t!p���[�,�V
�A`
 Z�d�����,u-%;.�u�u#����p3��l�J���v��@
������0X)^�"��M/��3k�>��u_@3�v�8.�h���֠_P�N;S�*�*�����Bv�H���$��r�v2$[�?G�R�f"���S����
���b�;�T�x�W/�p�S]&����jo%��Q�jY�M�@~%�C�j��
�x���#�eZ�A�'S�;*�|+�—�ڜ�����iG?�s�}0­�4�/�@.�k��Zg�a����50�2,w��F�����BAQ��?�ͅ"���ܪgyY,O��"�M]�6n9�����#3�oJ�l�R���/#�K�ڢQIJ:em�e�6��XNZjW�p��V�loA�a[ue�(��F
C��nEc�W�r�PdI�J;��R��%��<]i��Z���U��\>��NL�Vk�ô��¸|>�tװ�\��J��Aԥ�9��I>� a:�eY`��)g��5���I�I0f鲼%��N��Y�Cj%Ӧ��ꮖ4��4xd�`J�;]	�#q3�Q�(
V��1q%�|zm���;�3}�J�Σ���7�D�F�HnC)���d�f�2�|[�0-"dš%�Es���S.�'\�Fj�2�`�d�>��]A�p��u.�4{>{D���rS�;�۰�L��nٸ��0 �/wy\��8b|���z�&��E+��]�n�Y��ô��¥��酶��i�y{Ru����ȹ
=�g��ͽk�z֥+k	)����(���7h[�-K[̸�9Ь�:қ2�C/r���ŀ?��k^-�Q*��Z�Ò'T�a"��6L�3 �9��H��"ئ����Ǽ��s�
a��3��kv�{����W�R�T���Q�R���PN�jO�^��e����4�V3�/���@oJ~Q��$�ކX��J�u�!��E(8�B^���$���Q�¥��BIl�&*���Y:�/�;ա(��w��s�N4�2 �j�	�����fH�0D�T]��{7~
ڮ?��M�&���ѤH7/Lh��e�-Y$*)-1AzO�r�ԩʻ��Ǐ=��*٣�Ñ��3�Y������6d`��٬�Neȗ#�Sy{R��T�b�T�384C�K!��ݣ���
��-+���0@@����Ǐ:qȪ��LЏD�CIn���X��5�D�������
���Ht10|�~�������dǦ�i��P�Xe�J밹��SZ;��E�+)%�V���#Rh���O-�҃^>�x$M\S%aw���&��c�ʈ!�.vYJ�u����.�i���/�8X�〻I�6CE���p�9�i�m�r�7��gG
�,�P[c�'F�a����r��?
��?
x���Ҹ�3��j�g]�
����T���H�7`:1��g�9,�f`E�Q�Vq��C~R�f�nƻJd�H�H75
��ʧ��B��\���\~�����+L��Z̒�Z�H�]��b�����MRN�:��Fdٺ��"\A/Y%�	)�H����9m��/i�a� ��=)��ʸ�+���Ip�h��cҚ-���ieDD
J��E��*t�JR�#��|	��>1�U���p�G^P��kC�ڝ��`1it$D
�*G�7Q�s����?
%�Ғ���x�U���-k_	-�&R�"GL	�ĕ��2蟪\�ue�03I��F�R��(��6�נw��@�މݭo<iaڅN������\!��E�X�Kh�l��b��*%��O'aщ�`��
t�sjG��4���(v҉�cvO2�//*�@�nl�X!F
c��.!�3�����>>�N��ռ�q� �z��T��'r�W��ǘ����0p�q�0�|\vK��`��Ks4e��Z������P
��Lq��q������}+^\R���.���գ�Q�K€`-SqBB����K��J�$N�A���q�����q��y�TF�ƍ5������Pd���	�LhCX��C�몷U_��8��D;��F�Y>'��i�_���
߹ظ�E�:;��Y;�YԔp��<��*�B��[5P20�Uq���AM�]�����7m����{��j^���͏����'���*N��-��:��M$�KR�����������E"�7�䄲R�U��qd�n`�5h��=��]��H��4Y��O�`�{w��s,CC�Cm\f�Sg�� �z���!Apg@�2�҇��DM�W��߮����0/D��lv8�)YE��i�F���:c:���m���&��.1t��P�K�T艱"��7�-J嗖1��,HVcI"]_�`^9Y���ء=h�iTi1�����E�Q�F�����_���|XTc%����N� ���:�*b���sJtS!��m��)�% �4xN�{��L��{'�J��RBt
)ewo�D;��	S&���I5��;�������	B��^�t�����R�iv�pm��P��������Em?���NkCJ
�l��H)�F¨31ޟ<E������pǝ@���eԏ�ٶ�x;�0Sm�uOEJ�J��$w. ���0������Z#u�;6�Մ��B���*�;��ݶ���I�c��t�	'@LR�@�@d�up�m�Qې��@O�g���PI�*|=���C�?���E� /�L�$$��EO�y�B�>:��y' �>�`$O�f�0����J��S�@ 75��IO�(��s�W�q
��x�q4`M� �$*ܴ}�� �T
/J���,�?5���L�S7�b����zobf��ɿ���2��P+0C��wT���}��0�A����(�J�c�ڗh9�'��:�D4�B��C���������e��ˀ6��*��h,�P��p&*5���*	!1AQaq���0@������ p��?��K?�r��"[�����D��χ�6(�n�8�u��Mִ�?�
״���q@qP�ёI�:��j�-?݋�zVhD�ި��P�ٍA�!5-�{����ӹ�u��8��|��n���mKާ�Oz���2��$S
k�Gz�J��A4;��D���t�d�4��ua�ؠKRO.�j�-�;�z�D���5��=�6��Ն��z��ޠ֝���(4�P/X��i�4wP�X�V
v�zg�w��]�7�-A�=�5R�k��%sR�]�>��`�0Q�E�qӴ�H��<��4�⿼�yM�1ѼqNG%g{÷�֘���ڻНj:��'%�ό��txk�=ИN+��*Fh~����f�����$70�h��)!��j�~(���nky�߭��G5�RkH)+�F/aw��>U��秄{�N׆ܰVCʠJ#X�
��-���I�`����'.�_%B��T螔d-�&Q~���N{4��hRSA�"�R�$�
d����$���_5J��T(�2�<6�ޤ`ʒ�L@kzE
��N%��^ ��2��!�;��j��K`r3Ć�.��a���ݝ\�sP�F��F�m	�R"D�A&�u����/~̞&�����.|�)� ��o�_Ȣg�Bo�Q̣�+��(	�4�Sz�*�C�,~j
&!-� ����&N͹-�T_(/�L��y}X����|jN�O�3����-x��I���DŽDq@��4�]<S����z�D��4�����U���o�MF���+�zL(`���_(Hy�0ޖe�8�}�h8zڝn��4���+7������;��l"աzm�#��WX��6�y��;2ś=ةN'�u� V�A���8�*-��Ɋ�Jcζ𠂁U�f�gj@gο��R�Ae()%��gz��{�;�cߺ.��j�8H��)8i%I@�		K^	�毾*�e�o�'�(���B�ɨ�F��YE�oɥ��ˀׇ���"���}(,D�.QEu��Xؖ��S�:�?mI�N�^�9k CWI�LL���Ix#Z�ۋt��ҳ��.�7�JZ�#R�u��ݬ�K��9}�8��Ζk���o�OѪ��D'�IG-����uϧ����O68T���S#�i�fU/��f<��ƴ�k�����C�r��2�wf�}���w���@B�s�=✻]���~k���-X�c��(ݙ��#�1/��SN�#���T�{-�-~9w��Αp7;��*J��IB�u��k���_����*!1AQaq������ 0@���p��?�ȷ˙QH*_���q����^
��������v��+ZĬ#ɸ�Ā�z-�kO�L.��9n�&���saRJ� 	��x�8������cS#��F�
��l�@{�0>�J
��5i��{�ssd�y��B1��18Xm��ˆ^��~��Y����(.��qr��2!�D��1^%p6��Ԯ�0;�@�g�`�0EP�L+��K
�G(�Ts��ˆ�S��dJ'O�i�`
�H�*������/B(�E
�µ
����``���‰��M����Jދ���Sg�%���ҥ��҃��رy�J��6�8�wc��R��_cc�`>�C��>�0�:|'٧�–�����g{���`�<�>gʱ#�b7��rφ��AD�*��=�u��,6Ɉ�7���l:���d¼�ྩ`'�)������va���b�мk~M8;����ަ����8y�<��<�<��m3៮�M�Ja�g�5�F3!��e�W�(�����a�2��P�
�g3��F�`5b�o�3Z��m	��O3��H4�!��4��ĩUu���7��h	�g���EH<^�����v��������s�e0��)�̧H����V�ϜRSE�.�� %1)����iɗo���L�:L.�.��������9״��)�W�WC�n���2��c�?v��p����&���Lv��7h�Qv��ˣ�D��>Ү=L��B���z�G��� Xx�\<Q��DRF���D���P]�tZ JiK�x,ޕ2�z%[��4u�(Z�ƾf�Pŕ0��JE�z�RJJ����떄�^�ђ\�]}!S���c=qc
�|C3h���K��V����Mȼ�=c�!<����R�k��`}�væ_ȀK����˙�8ũ��c<ɶ]���6����V�H��PI�41{�!P9ԂA�s#��>HXˣ9;�#��)�2��� �=3���>zJ�Z!.��!NQ�%%J����|�U��0�-1\Ǵ|`�M���^vm���~�����}�b�;C��	�� �m����C(���v�`|[�q�x�#������+�.�(��M�tT<9�&�(�<Dڱ��~��+ʿ�u�*��t�
��b�Ϧ�C��u\.vO	�1�L�+�M6��ia�:�?������.�aU4���Ӫ�UQJѾid��aC5
'E���.8������;|[Ƀ�������f�2�+�V��{�VHH�Eh=�)$��OS,�8T�
���\�T�*dE��L�����n<���h`گ�!��*!1AQa@Pq��� 0��������?��4R�Ux1�T���-�9�K*%G��Q4�ਁ�6L�S�S5��o��xG��}8��?l|`�K0i��ČPG��`�h��iMz�M��)X5���"���!l`�0Q¬i�""$�9OՑ�u}��W��f����܈^m��D� ��p���fM5u`�G<���~�5@�""i�/5.@���W@a(/��xz�!@�}ݞ8$p�
�
¦�EW
x�^����Kn���q���sp@u�u60A����w-��P��
�����2i1�4�.��$��@�2�&u�:
(h��D~٢���^�L��i���n{��4gtϠ�A���(��at
|k��J���(%��B��ͮ.�D(����� �ID�X��e��y�e���
{I�2���q����oٗ?ي������7�>Cs�Ʀ���^����̆�0(���;i���u�<lp��7Hzk�ߌM�T��f��.��cNF�ٮ�����)jf�?���z)tr3c�-�:�hy$=�4��Ȣ��&��SYa
(5���h�Hb��(#N��W��!�;6"J�	2�b)8�<}Cx>�Z�9ͳ��O�E3�"+���c���IZ8��&u�I�)��&$+q��1��1@�flq�2����	�e�^���u�w�(JI6�"�Bt�iF��O����)�tCb�Kb��f�Q*=0�d�
�*\
�P(H��*ct�|���a�fؕ������^Y�Y0o,d�U��tQ'"��P�Dаn�CB�Q����
 6u�K���_w��1����3�͑{c�oƋ77Hk�d�T/��G0�i�m��D��9��@���j��r���)��1�ܠD�Hm��K�Lgfz�ϸsb�
�:?��&�{f�3C��N"�b�i���Iv�V��1<�HQ#�n��*IY���0�Jt�L:T��Fu�6B��k�3�Q�*�◬�\�
NA�,~.�,�r�ʴ6��D�B%8�Q����ƃ�Ʊ
�]P\��+�����=�x�@f<�d���3�xuhgl����H@0��Y	4(+C7(J���
SI��T�@44�����R�d@���x���T��Z�wG0��"[ȹ3ģm�٠d�P���;�@��/�6�U�OM"蕐���p��u�4�-.B�m�8�(��$�q]\�8�q�o*��O��~%j��b` ڶ�+N0>dZGX�k���+��38 �Bw�dK�b
����βy��6©0�#Z)Et��W؉���B*�@�ʧ%�4�����^,�A������R�QWO.�uQ��;��^b�o��i��D�����u�
�.�%��~yW�U�y�œҾ����`5n6�;�ft�zcV�gd�h��__��
f�[�U�q�9h���X�ε�xi�3qc;�p����@�}����
f��U�?���!�)��J��!;Z�U��v�>�g��!]�U>���VU��y_�U��.A�vpK�������I���`�	�o$��PS0�����>IuH��D��n�&��#\���r"�Й
x8�Tu@�dCj
����v�]L��h��mw����U4��~/X<u�!���J�a��B�OL�ќ�B�i�Kf�#Qz��VE*�x=x8���H�;�
����/����	'r#��9����(�@��sa_H$8 ��&�<p1�$M��-�p}1�̀[AY���N/�چ�/��(�)��C@Գ����aSb�M��ѫ�KYn�~c�FfZk�ҹ��$H���M�9��+�"H�p$�df�Akl#&�5g�B�"/B����R�JT�V���B"la	�`�.�(`+��G㗭��;����r����%Lr��UlE]�%w_Z�m�,�%hE5�m ���@�HP�Qfh��rk�\�ٚN�n�ל���*<߈��Si�R�¬nپ����K�T��4`;�q(�|	� j�H�G�?+�oS��sze4�a�"!]1�}��wCx�VkS
Ÿ�����[�ao�g�$��j����(vrK,A�2\��I_�@1b,ˀ��X}S$S7Z�J����Uh1KL7�LlS7z��aL�(����}%Ӆ��m!R\�Uz���f�>����(TTS\/7�Yg-Ÿ����;�S���n=a��b!�(�%���z�T랩�D*�;��8
u�sS��u
Jcu_?SY�W���\>Ltg�^�p���$Z�-.A�u�G��g
��˄�Ff{W-A�
�g�\��8V
��k�����1^v��'���Aԍ9�Pk�u��'����8�rC�Eِ��酢!\o�
���;�cZ�_'�\hf3d&џ��0�� A� ]KL��j�2�',�]��,�s�9�Y�3?y�gdm��8�1�K��o�Ɔѕx��h@��3�� >ٵ�;��-,���҇�D5eH��S6��b�s�:tw��!��i-���X!�t�pFi.�T9���e�޻Y�����6�e�����0�U�D���1D��g�3;�w�9�s[�}3f�^w��x��j�,|O�͍
G�#���v��\�iX��ᖲ�Z���9����
ô�%��2Z��0�Rthx֊�^�"��4=��M
�$R"��Įw<�p�5�HF�.܎
�0*>&o�w�:�*�P5�SX6]Piy74��I*�B���,�V�F�&@�E21<��Ao�eS���9k�\�L�7�}2>^��:���Zb�CE-��kh���+�/r�$^B!p��G*	WJLU���svc^X�fV�Uc�X�G��������t�vR���!�VDDOAn��\zb��i�
=�.��H&�f�N���FK)�!��3�$��,�R��1��u�@b�+����D鰔bh%ApaI�_1�*�u�ws�\,m�^x��ps��P��&��@��`$.�t8��z�|�4� [xU5�H��hd����4���0>���;X܀[��eN�f}U؈P�Y�BU�#�K�
VV픻e~Y_�J<���U�1�U!{���"r���.���'��Y�TS�KP[L�@��+!L�)B���k�t%��(�v��x���W�|
!6�5�sO�^v��d��]���3�^A��Pn�n��ȢG��b�+n�@k��]�,�wB5�ĠU��֦�#dih���`$�2�僺�W��'�-�j9(N�V�s��-�����B�z�&"&$͇���s7GYL�B�ġ�)R,<���L�
P�1��W�U������٢���I@̺���AJ�B@���R�eJ����6D�	�(0\�fS��C�ܘ��;r@;E��φ$�\�� A��X�>y(��` 4������жaj#"Q'�I	�+D�G+�(�n'E�יI�w.��q�l{����8�.k����t�(�G(B`��R�����s�i��Yq�����0nr�vC��4��*A�Q�Sn7ˈ�����H�)�`H��k*k���+gN��y�~�>��Ղy0�..=X�B��F>��焢0���4�.����r�cù�V0M�Iq���u�"P!������
� C�ЎEx��)P*[�WWDɸP�m�dC��4�}Y�a�(��"Ke���NT�p��K܏���7а�\�4���OB�R[Fۄ��4���`���!
���M��	��`=5k�����/�*���H�:��[l+�dba��ˎƈql22ut��1�P�"�@$Z���0�E� F���H��F(DovaL�@�c��ע�Qh���ڂ0��$�Ma��P��9�r�H���5�`5�XH��m��˗+0+�I��xa����ED�*�v�����l�	;����[����P�G �儉���/��+�����RȖ��q��9-B��c'Wz����D�8���r��6�&j�/��Me�Da:Q�o}w��mȁBkR�5h1]mR� ��*\�'�q��I��J�2��@g�!�������Š,m�X�q�Zq�P� ��6����@*�Q�(\��_����R��k��CÛ�Ti�"����`�t���1�
���F3n.5h�&��5LH	-F�R�_,123O���0A˄�=�<]-<�	�����y��<
ʐ:��=*��-��E��;� )�c.�O�J��-�#5����*�e�mi���veI���y"g�z�}�.�U�b���G��O$<r�{o7����?�y{slن�3?M������M�H{^�h#�"Ŋ�zeК�P;��-2�d�o���d{�"z&
ˎ���"�t����	O�d
^�K��88�ԍ���-����R�
��"�`D�.f�܇�%8�.�K�2e[g���� �Nh*�RƜ�m�Mݭ��6�:���Zv>20X��'"ӿBo�t�!F}���DnB���,���G�>��c�b��T�v��w������1}<�l���~�9���'���`' ND����!|���,��R�����Nܹệb�������ܝ����6�y��|A��J�DG7{f�l`���z๩A"�Ƚ��""#���3r�� AH
 I9��APa�mb{��ĉ#���V��T�2�p�^�(ð��F�D���F�^#yV#�
�5kcIT�c��*:r��h��tu��9'��'����f��C*.�,����0�����-^�>V������%�<��!�������6͘@��G=�M&��;��b��P0ف�,Pq�ίLxtLJW�)��
R��@x�޼��5��a�/+L�h8���#���a���pP<J��e��%�* �ئ��Atu\
S�&�ޔ\�wKSqD� u�w�����ٵ�=l��P�L%���-^�o]P�0��1�>T�eQ-i*Z�w����W���>s��@u��DB1�c>���@h5�tCX�^�=ﱋ�R�<��>�_s���7���2=����ݧ&�)�?q�f���F����2��5�I�W�xN+V��{���uNE�S���(	��"!���u�i04$R/e���!�i4��WaR����e/D��$�
Y�K��L�S�y���Y�r��%˗S.����	���`�����GJ���((��Z��3>i�$�i`�
u������:�Hp`����6�/<1xϩ� ��B-�(�r�˗����	Z[����ّ�Tq�@��>C*�
����RK�'$�9T���`�p�a'���4�%�F�b0�P��.]0n���
y�
�u ,$(���D85�V�V�A>�I�?�{J�Z	[�D��0�}��Cn�2�_\SC4KYi�fG8ڪ�
4`�k�G�H���*>y��ɱ(��~�`d�1�X:4�
Dl�u����Y/�
�`鼊x�v8��Dž��HEAʶu[��-l����Ef�&J�-��%�PK�|�g�j�R�����0�A���!��0����N#�!2��5l�@kH 06
�4�^z�C�"��>G�j�k��]�HN�aC�C�
Z:�U�}ܳ�����uF
J-4(�(�����d�����q弌�HZT
��W�F����lٸ�''�H+Ӿ��. ,DDL$ἂI�I<�\7��Ҁ�����A�8`T+&�1�oU��p(��޷B֍���_n���%DU_��Z�ӓ�Ȃ"S����N���8Z�PMEAˁ�����5��x����pB�<F�܃�V�R�e�d�J�L����^`E�o�aR0��A>\*쟐"f�1NX�PZ�cb6Q��	��=�P��7�����W�@�	h>߾d"��U߯�UR��G,˓�q�yUUU�M�����A�'��hM4h�1P_@��rX�"��D(9�k\0OX��Cs�vE�{��ߚz�6��k�'��&�0_]U(�GH�l��]�-�HK.t��������8-`;�	o!ȁU�aa5ln qTE��L��F2Cbb��)R�*U�es7e�^��͞�0?N4���*�6[�S
�Ƚ*r��6�La�`��p�s�1DAC��V�o
��B[v����p�k�*��
wm�>8j�C��٪M�����|Bor	*�#..���Z�O���~�R�����������6f�Zm��X���˷DL��y!p��:أ�p����K�`P_F�Co��7�B�a�	��P�ɩm���RTID��U�8�p
̵!�lw�pE��*���`���M��!X+AӡM����/���YJ�pL�x8�g�"��A�#�,a`��0��n�$i�����w4$U�W��90V�ؼ�G<Þ�>��
�c6��}ߝG�
�`�c�[-D��`c���(HKK��@
LQiU���!c�o��q�[)"V̩N����˭���Qs�4NU��אp;a��׉�a{2g�,F&r��'�3$�](_�Z��W3�J�lӸ��ׇ��Ω8l	MTC딖��ڴ
���=�M��Q��

�,:u���?x�>�/��h��LG��[��%�i�/�Ω)P
��R���m'��TcX�	�A�<
�K(�p�v�+N���3��X���B�`V
�獣p���l^
���$1I��U�y��A�O�iP��C_smO��P���ɢG��(F䁈O�iT����s��v�]��#L���Gb���
endstream
endobj

6 0 obj
<</Length 7 0 R/Filter/FlateDecode>>
stream
x��}ˮ$9r�>�"�
��	ܬ� `�
�b0���4���M��Ў=H�p���,MIht!��N�f�4g,w������y�,��SK_ҹFw�ٝ�����O��{rg�߿���[���B;�v���׳t������-{���ӟ�ij���ѿ�rrK��s����v��_���gw��_��?>��ٹO���>9��r���|��>��������7��,���'3u����������O�~9�Ö�艂P/^)����iO��J�ӿ��.H�O��x��?��OK�\�H�g�?QO�l�ßid��?cH�H�����\?-�F�?�p�&���|��>T"��f�'������p����`w��;s�)}���1��K�fr��	�e�N�K�&�_�Ke��Y��0�{���{��c�k�/ޚ�6�溙�_��<\'+�P<���^�Do�]��ͭ���cd���R��a�$%��z%YB�fb���gg��i�4m��{#O�A�̭
�zD}d! yI��B7�	,��;I��t��	϶�37w��/�̠w&�-*6�D$��A��T��f�@~u��/�E*|{��خ�4q�[H���Oa��H��'�����Ƽ����s�S�6�1<0��ے�0
c[<x?isRma|���
�2ԣ���w��'k�uߴf<
=��~+cW�J<�����.]�4Kل)����[d2�:b�Z��饙ף��Ǿ�
օ��M6���I���8|���Q����ТS�, b��H��^0Y4����ل�4#&���~�IH����V��nϰ�W�p�
�CwV�,5D��_�?��y+�GV����_o��֟x8,����U/����
�##�{�>�o��ό?~�M<p…����o����?��ߝ�u�����.N�Ư����ʥJv�tǸ��
Tf�M"۝
���K���pwC������n]Ǚ_;4�x�>u���j���D���}eg�Nӑ�K��6��}���sj9�4������D�3�6�S.{�M]/�@����
p�(�`/�>��$��s�W��E}�a
f�p&����K�:t�������Ŋ�&������y�m^��m�3���X�u���z�Ұ�Z�z4@|�?M��m����E��oC��īU[�ϰDiX�A�7�4�G�Џ]�?��:�x��V��K�6����	���������3�G�����i����6��tb�������ޘCy�n�x��aY�v7J;��w�vh�#����1�����b�$�r�����w$_�A������]	��+I���p�X`��[±�}�����0o��9	���?��<��W[�h���{;��u�wǖ/ex6E�y�wx1pUT��v�g8�~���@�'�g��s�n8zLS]�r��~G�:wi�w�aM=~���y�~�Z~:!�c�9U��A^���Cp�a93�K8�v�
/�
��;Uo��Y 3ׇ97�F�&��-Lj2�q����|���$/�
oJ��y<$(��
������{����b�O���_�_J�/��̣�
�������[
}���`�G͎��'3D+�{�I����D&F�X���أ��b�Ʃ�G��q&e�4�;~�m_�������q�HG���8��~8�wہ�4]�w_��O6v�&�$\b��Q��xjd}�����l��H66
��P���EcE��Y���)���R��5�
�1������/����5����\WD9ֲ���NW7�g��m�	n�c&�����P�c��XCp�|n�/?�1f8Ԫ@���g��Q����8�Ϛ��8�Hǚ�i���<����C�C|B�#�^�1U!3��Rs^��#5��R{�V��l~䭮����[���_X����ӜS��Z��n�����ɍ���,v.�P��g�:��_���Y�/O���xD�SL<V?B��[��N4������K&X�Cq�/_9�#IJ���8�1��v6o<���8��7��)5�����.G���qt~y��@:?�������lS�IϦ���04l�.i2��-R���}O]�e������A�m��6��#INy?�B�|<Sȓ�/0��_V+m�3�$!ؔ�)nk���{��W������n�[6�)�<���zVV�)�4pm�׉�
CoJ[h~�]ybm�ȝD�\��1l��_F}��k����*h`�=,
u�N�1,Z�< (Uapx�tO��Y�bO���3�����gs�v�V�|��; g'y4�ˇ�<���Y�M�~�hΪ9M;�̝�'>����=X�?
��|1��-պ�13�����\`���l�͟��Wn����7�%�����5ʐP�ĝM�sU�t|̺�wŞ׵y��е}r�ԵZ>�k�(�~]{hM%^�Ѫ�͆�掷}7bM>:��:��CV~����w��4�=;�c����B���
0xR�d�J^�ԭð�;��X��4�������9�>���yH�`۷ݵ�[�����rs\f��VY\����͹5uw�[o����Ŵ�H٫�><��k9�n5胖c~y[��)`��_a���y#0��F`���skG�|(�v�����zv}6���h����I�e��~�-xL4�'K����8���A��5�r\�;~�E�m�vq7���\��2ŧ�z��'��Z>��ܢ�?�Xh۫���\سq9�K��<����i�L-J
�Ӛ��.�.������ j��8J�.�V��?W�n�����h�&k5��?C�5�P�\�a�nUvmJdf�ɟ�����>nrW/O��T���Ȫʁ�B�>BAw]۞�ߙw����M�ƃ���J�#���Ӓ%��峒5�L��<Ua��)�Xv�ڣ޲��!S	�j���\=&����T�v������S���m�Q=T��)��q $��T}1}�{�4]hhv	3��_b�4�_�3������+n�n"�W�(m`ڎ��r09�p)G��b��hs7�޵.^�����>!�Z����~](/��/��|x����ϿI4�!7�La��%�W5+BW�/���]>�K���m��)�d�y�`ħ���^����ԛr4|���\��_�W�������C��fE{
y��A�!�_0�����#�O��1-
��.��$�>sg��N�ק���g��8��y>�?��C�M�~�b�ɔ&�(��w��>��mѿg#k�F��B]���iG�ݔQ��d����
I��>��1��<�����B��y]���S������7������ּ�{d������0�ռ}r�KI���M��Hg�W��ՔMMS���*�����[��Q��}߄/{���5߰q��v�Pe|7p�N�P;t�27*ǒƑ�d����[��9+����a9����S��C�����7�[gp]Hl����?�~����)���>9O��-��[���j�k��\�UW����S�k~�����6��vH�m2�{����,��i_AONN��6�<�u}�SF�_�2��#��x]o�`L��g��/�K�(g����E��ӍA��m�^v֏#�C�\(����t���L���wg��׳f:��a��T>��[Y}�j��OG�$����i�~}�i��|›dt��Co4�0�~�צ��G�qY�4iCYݤt�P˥�[�O�Ӑ�û#v��y3��n����\'��8>���z�N��z�=��k���nBۤ�����|�s4�h:z �-
G��5=$����;��,�����j���%�*W�h��#����
��j���96�O�B���s�%3�����ɕs��j|'�썝s��c++q~�؊�6����c~����+Y�j{h�7%�'�.��ٲ��d��}��y��Iv8N���n�@�O7�o"�[�L�.~<�Ak[*��
���n.��|��~�uv�b���mL�6읜�8
X��s"�)�c�#>��%әb��8O|d^��另��{uHGy�#���6M��̻KَV�4��r,{�ʮ��O�3_���M�K����9e�y��$i\�$�9O�fs��<��Y�1�~/�<���A��.IG,�>Ha;ꖽ`x��s�'#w쇳����5�3Ol����Ww�6�b~�Z����Q�?����^\���$R�y�g�;l_�8zW�:�B��?z�F轿���;�ƮC��7�n�˽O��h����>*��L�=d!H���vO��<���C��b�5�5O[�xȠ��ơ��ܗb��{Q�C!�����9��?�ڐx�5��/����c����Z˾-?��K��pf$ԸdV���&>�]����!#'�Ɍ���04�q�'�y:��C0t���R0������`h~�Iڟu����� �d��x\#=9g�G����.d7}sg��oW�t��
���Y��,�G�q�����p&w�9��i��k�n�7���*���3��f�/o��=v���ߤ7�٨T��`�yk����8z��ڮ����Y�:yh���;�Q8��<�̻@���\ZLK�Kh�~�K��˒j�!��t5d<��.	?F'k}M�^2~ 'm	��譂���*�����؉:2u�K�D��n�#r��yʓ=.����d������v`ѯ'&�����䎾�ئE�ޮ�i”(k��3�\�H������ 0�K����#���I��m!��Xhƾ�AF�B��_�f�h��t�-�ﶅ����f�x�%��/�
)1N,�EH����gh{y����|���$��R��藂�d����_�%$ty��d/ی���f��(�蜨��M(=��7<�SoQ��Vs� TU1�I��:
�NFL�@����0��^�m��������Wy��ި<G��B�G�au��qv���e�����/�o#[(��;}{��m��-2�Ԯ�*C6��"�������h�$����jM�[pK�*4I̢�$Tx�*Y]
[�,��<�C2yY �@U�x���dR��t�r�\�:<�*/���'�2?%x��٩ڷ\�2G�s��E���G��<s���Հ��^�I�v��]If(��i�S\�t8�����XWVkd���8��q�/���R8��չ�VT�P��@g?|A���I�`�Pq�U�5-����&1��o�rܡ|����"���=m�Ę�o��Av��MZ�&�BT>2֩�32��34�!	Q$�n�_<��M��5��c�J�0�g1�'�1��4��!{U	�\X�E�|`ӚT�:�E������uN��l�� M�1��郃R�x�u��J���F�i$ϋ5]�vн����0U!+	A����w4�G�`4�P#ߦ<@;X۱�T�x�a{G���u�#�u:�N

ّS�7@�;N*'�rP��CzL�aQ��oVa�Jm&}�_̐4L�;��Eۛ5��ZV�.Y�Lh�C�*���^�g��<OJ��2fw-0fU���-՞`)Y��A�rc�ޙy�h����r�{�t��Gp��"�³u!,�����O�\���1�,�n��R��4/�����1�5u�llC��̌�6^�P����˾d@���we$�A����S�̺����*9���F�Lj��:��Җ�>��#��G\&{��DR.0v��|�-3�sL	3��N�X�A�K�G�؈5oȐ:�ܵ
ﲷT:�{r	�q��8�w�E��m�A���.I�1Bފ�1>FX����ۍ�@�Po[����u&���E��J�*ͽ�p��j�EgHZ�7��#7��;�C�GbC�5r����v]�!p�>Q[�.��6]c�:��C�w"���I�#1��M�X�E��;
�$����v>;k���=Ilue�B	Ft����E#�� �Ŕ��}<�%��3-��Ǟ�X�c2tL�Z�_d}�jCb$�ζ6��՜e�k�6+LM������6�^��
tk�D�9�!�}��>��ޫDq�9Z��k��e��DH6,�Y��tf�P��]E�[/o4��_�<SE[��*�Q��`R-�*���lY2�ː�� �dN�Ep���$'M.蚒9�jK�P�H�8e�HWEٗ���%D|��#���&��C�.k�Du�i
�D���[���,qs�I\`�6,`k�t{l�Xu����(�(c}�������COv�zG1@����zf� Eh��
@��=� ׆&�WV�
�'������ND�?G�NUN�Nds=K���QAcP�����`��4Egb�xL��u4��PW�B���
�)u��4���SW��
�$�#B��C@�w$��D��ˆ���v�6��[��v1����DR��(i5b�ug���0U��"�*�����"խ�45H�'剱�����_5X�?K>��`�xq�<����.�M5,�rY�M�q���&��Ϧ)�� oB~�ᨙ7�m�Ahc�:���N'��<@����$�!��:��p[9���Y���D�9?B,�-��P[�q�qT߀\.�,q1[ۭlb�O�+$���F��y����k6�URH��׈H!�����z�q�6Ϋt�ϐ���K)�~JA�2��\�fk��?Q<LҞ�?�8���@�rm$������'F��K`:y�4�H/�������/�Kjg��� ��|���C1���G�+
A!��q��.��^��Wy����@	���DNm�0{�ڀIڲ��K8���0�)�@m�'�Ж%2��
�Ӫ�E�R�ȹ���|5f�y���!8�!ӃfW0�f��'�D��>y��2
8"�1�Zr��(�p��"���H����aN���Ei.�Dz��e�=|H�b���NI�ro���6���R"k]0�4K����v�Q(@��L\aV��|�����u�US0���R E�Lj}�5��R"��-?�h�.&���F���m�H���T;,lk���W�������fNle�n�0Yb�u�������lW[�p�p�3��O�@b
���QsL�X(���M��XM�J@K)<ǿ�V��� ����P�)FfGl� �-I#L�hW{��l���Iu��[��%�8���
N"�F�+�A@0� &��(�xuߨ��zEmP��L���.�R��O���y{՘�a|���y��p��"���H���'�$��U��p�~.��I�U:�K�#󙠠�ۅMw]̿�PPU���y(�yX��p�Q�yd�q�:8�V5��Ǫ�!v�ݭb���g��Z��U����"�U����Ӡ-�`r�:�)MF;Zۣ�W���ng'����!rK)���NǛf�Ƃa�H�����h$�v��3�@n�?"�f�zg��X4xnBZ
rK��NE0&��`t��e'=0o�[�1�啀@�T>@=e��D�n'
�J�;��;��Y�P���iVԃ�90F�Ɂ���OU�&"J DZȈ�D͔��G�E1�Èjk�]�V���R��S�t+u��z�91 E���!�8��s�����¡=h\�hkW^�U�f�:�
�'�����o��m.g9Ң�u,�!PL������B�Ű��]o��I�0J�1��/ޏM6Ѧ�N,�M�81�49+K�&x��&n)����Ll���L5��E�,q-�#ZG�]VQ�C�?����0���D���4<�l7���Z���CKE�'2�V8eG;�xo����\5���z�Em���{U�ڛ�H���G��@0�ZF��Ht��X'�H�'ZZ����4I�A�o�a>r��,\�Dޔ����R��	��5BU�W�)�
M���.�?�c��
gŚf婣�]m��2�CBl�<�)b߬#@�t�X!ݫ�:Ӣ����ߴ��s�2V�MH�=u��rb�1�5/�yj8�KΛ�� 	(�'f)��Q�aÚ����$����X�����v�ߔ���N�J��*���k20G�HUVة�y�hCH�?�����	�p��h�(p�YL�*4�NZ���;�pvF$]Pன����M��<g��pʩ�G4���3�]�s��+�:�u�B��+�.��f�Ҵ��,�4`�_�d����6g�@��*Sc/N<�S��b��)\�#�8��lՈ�b��gFaX��LB��Ĭ���1E
:b�!��HQy&G�B3��IDeg�Sh�UF�j�bP�����s�J	��a��`�*�z�Ѩ��&�?��LbCQc-P8"h�����1�8�_a9	�4�,�#���G mU�A(ghP�M!޵�6E��Po��Y�9y����dŜ� ���pQ�HBD$�4y��"X��IH�.&�i�H~l(��id�b�d�bd�����&�\[$mNVpC6�&C��z�yR�x
�H#�YZ< o,:D���Ƥ�/Z�[ Xw����+��H@��l��ƚ7FuR�+Kg0�w�S�ܵl6��ͮ��z����[{�$,�X3�.X���)��6]�4�7��1X�B���4�e�դ�(��o��<U>�m��ȼ-�B
l
���Q�s8��R��|�����7mIoۈ(�KQ+D��Q�QI��IWM�?"ԬQ{�ym OA[�gAk���<r�����7�U=���UĖEõ�a�o��[��bO��I죛!��h�2A{�y-	v1i�Zr�u�W~\!*�?��v�{BT{N����_��<:�JV�*�=e�d�硙n�ָ8�P�#�F)��R�Q�:��y�AL�	�W,9��
�$m0?��d�d�ѸC�D��xU�	_Ѓ?j7�uJ6��4u��������1�uG�&c�ts���R>�0��45���u`�R�˧�,���jlE��ǽ���yo��s��ܮdN�
���d
�Άv��m�+�rԑeH���	�X��V���l�F�2j����4��Lo� �$�TU�2V��L&��,�^�H��n6�щmb�8U	�ʇT카��^u�Ū�)�RP�;5F�a�ɱMV�/NE6.PV:Y�s��t<@'X��� �H��)��s�E"u�T~��&{'t�z�h�:�,�$�������즬��3�2b�7�����Y���G#�"�!
d�LYN6e���c>��[��g5+�
��|��D�#+iV{�̚�3���񈷖N�������b����i(�����z��H�6!;��xY���,�n����=��˄�j��ȥ�*-�ڒ+D�2u:�$���@BM�B\�;�)%��� z�tf�P��lH\픔�4��#g�R2aJ(�IIk��pjk�N�����~��;���ѐ���\M��(P�`b��@1�
����A�8� ��M2�V�^��4�K�b�}�GjHD$�B�sX}��,�r��]������Ī0��N�M�o�8�X[X�0R���jb���2�8JV�����6��I�P=X�ŭ�ʫT-����zC^*J5ؤ�Κ�ѬLv����	�<
��+v��o��yo���$sx;�U�T�ё\����0����M�u��Y~R�oY*�k�7#��vbX?���|������Tv��t,;�(��
0ڰ�ۚ��\��]3�Lq�կB�w���×l���Q�SVo����}�h�~9H�q���]�	�-x��ʴ�f�6(Fvz�5<�fx&�O��ۺ1��x!�N6�+�r�F	9+�L~:)+ģ��
�TX^�<�٭M�p}�
c�͖��_8��U����
u�{F։�ܸ#���������7ux!*Й�hc�]�_X���
b�	A�n�d7|�jM2�[2/L�k�wwqa�&�	�U1g0m&rK��I�Qfl`�6���Y���F���ݴT�&%�k��ii�#�ȟR9[��xN_��:��,�IL�?ٞ0����DҚP��SR�ґ��bd�祔�p�O�e爽���4P��1�����>;�Fd��I��l1/��e�}[R��F�rI6%�g��bC��D"��D&5���<��c��4��������hԊ&;%�qQB��2�:�?Y��ڸCV��JK:��A:t�����G��:d|�@B���Uk��(.��(-�>k��8Ϩ"�H�5�HA�̆��7��X<��-�`H���S��
���,�����o�X,_�l�x�'����
'�"����]g���)̡��VQ�y���G�a̓�����m�\���m��ΣI�g�����-k�:z�,�>`��c�2m�v��U͟d3�V�(�IO^hI}B�Ԉ\���?Q�D�P���q$3��͕�ܑ���6(Yt�v$ۙ��54��`θ�C�u�),���r�;`��[���Ң��I���h_
JBkh��x
��^oa���n���Dk��+�"F�PɀTvj�)��䙫6����eSs~��� ��F�oM?������a"ߛ�Rq8E�Sc���з����������L��-�Ci��M��u�ʞ�V7��h'"h��N�
4R܄�<�+�)�e"P�G��K	�H}r�B֏�O^
*�-�u[ޘ��V�E�0��V�*tR�l#�c��o�ٹ܊��mͬ�\h�F��&k�j7#Â��=��~�v2�
��'�F�EGT�F�����oT��6G����1������`�F�`)���+�nj�b\�����m�J.�	���W��`�@d٪�b����� �5}!+P2��6Y�Q���:�MK,�:��yP���-t@ɺ`[�XY�f�ꉔ�hR���*�]M��U|&b��,!�P-�gά����h%3J;�><r���Q�	�`����{�"�)|�}��N����
/-���=�����
%�h���THs������Y�\/�H��e�%l�CK�=D��f�ٮP���:�׺�\c87���N�v&'��������z�مv	aI���_�ki�u���~�__�k���zݯ���k�n��mv^Wp���z]�����u��
��OWp=`�^�t��-]���uKx�����.����[��]���^y�.�����dx��u���^w}���z��������w}=�ů���#��{]���:��u`�������{�"�n�'��ư׍a����7�=d�K�^���.{]*��u���_���.��K��.{�[z�;��w�u����c ��j2��u5��j���d���^W���&���]M��-�^Vt^����o/{D�_�͓�.8{]p������g?���GP�u��4��h�;�^w���@3���ށF����0h�m
endstream
endobj

7 0 obj
11382
endobj

9 0 obj
<</Length 10 0 R/Filter/FlateDecode>>
stream
x��]K�9r�ׯ��*�����%�`{����Bc����7�I2+3+[j�f�	A�&+��`�Y�f�����\�͸r�5�\���${��������}�W����u�О�����_/�B��r������_�|�����������&w�����z��?����^�-^��G��~����ϗ�{)������G����?;������BC�[�=���������ژ�uڬɭ!��GS�>(o4�L�խ��OO�A;m,�>M�6|��.lk=}t�J�����{|i���0_n_ޞ�+i{�!a�8E�p�1LH���Ԋ��8,�Ҿ��Ĥ�
�f:����C�Og����Y�{���"��k_7$��t�
*$�)�0�^�wE��y��n,�[�{��}�����Ĵ��e���Cp�n��_�$������Z�M`´�X�b�|����N������ᷡW����	��l����p><@�q��r}n�-ؗ��OHo@���0W�*0Xpj��:_�j��a;���>H����k��n�n2��t��[I���X��)�������Q��[�Zu$��Hm�I�<b �33�
I����	�\-kh�V���mC
������R��D`v\&⻽A2S=�𬩡I��a�oa��!P3�:�%�Q>m#Q��O�qg�w���dW�l���d��R'��E��s��f��
1���^�Q��V��}�x?��i�R�-:����p�z���{R��g�lM=��x�����y֟�o��4��Ȉ
$�lً)��Z{�"+ b6��s�7Z���V]U��[xh3�os%�)�g��h��hf�=2w��	$ϳD�A�i�jne��_X���l�����;�fv0%m��n����`W~\*7��0�H��lzȴ_�&����<}��3p�S���ɫX�l"w��Q�M� ?��ݍj�V7M&��g|p��1�`�i"�9��M�]O�v�����c��(�`nAq����KC:w%�E�^�	V;w������#��?:
(|���@5���H"�I{�ǐ�A�?�o�.;iݎHA�nB�[ �^�����U���#�ư|0�|�
W@�-��e�Ȗ����=�����g9�da+G[�BIv�h+�?���@
t8��[s���^�.ou�\�4��`�tΤ�%���4��Ӳe��RI�����őA�R�W�oy[d��00�8}��CD�=��K�a�!J��,��5Ke��ݣY��n��+|�VyŸ�&Ptk�O;�Z�[X���v�������j!X3�z�k�*̯kq�̅ѥ�D���HɇK1�hZ65���I}P+,48�H豿R!�����
���i҃��P��V�a�{c��S���z.�yVj��>��O�6��:�z���VO/�/��At`�(FM�u`��|X��E�n7�k�����
�7T����22v�$1���w� ƺ���xc�]�nӻn�h��mi�A2��%u��?l������1=�>hK�瞠�1m� ���Vo��o�X�F�<�%�6��Q�½Ӗ���gYj��y��L�e8��m�2�X�*��y�q�w��8�������Ō����l���)@���Q�C��k_��t�Rcu'�("L\���6L빻���v�L� �^���A����8
.��8ޒ�e²���p7(�΃3=�{pSrc�.c�y���bu}h�ws-S�ߦ��c�4�Mr�����䦠�S_��9���2	����G��nS٥m��
�Gtӭ0����7���û��Fb��NbY��;����EO�j;��
�YS{�->�I��\��{��}�\l���y�Ԏ�I�9�.��G�/���;#R��L^�; J�P�m1�[�+���/2`�@�|,�]��Q���
�)��A�UThq&�f�b��~� �&��bޢrS]�N%�ŪV�}�T�Ğș�g����70��cbZ�PB����^����Ta3� $YW��55��J8���}�6�yT_��w��ե�D�20쯯K�yWdu�~|��玩��-��\\���Kj6G��
so<�i1׻t�@�(b*|�j�����Qks޵����r1�q�ͬ�7Q��w���,�^F�mvN��I��y(�����>�
͚��y������CW�$X�!�M��j���_��W��[;I�F��dž���XU�C�fH&�t�G_�-u��M(�A�6�!Z���	p�k��}T�gu�u/Ꝭ��<�0ű���pk��c��L��YOF��1��`|�Ձ���tB�^"K�����ɲ}���2nJ~���Ld�V���Lt<np�ꢒ�	�H��V��߄�a;�;�����z���&F�m?$�H�^�Q�(�+�S�<y��߭����`�(4�L����r��GG���6"��C�[�_�3�l0�C���B��7�?��baa
��?��/�-�t���~�"3����t��>?��!��i�ĭ|;0�밵s��^��!��rHo�ՃS`���J{���8
���},p뇤jE��*�2R��p�p>�U9Oܤ��.ҰIX�}�e<h�YY��?�S����_��l���rj��ޮ���mXe'Fᖃ{gV��������x�������&�8����K�a���#����
f��[Q���1���Rh���P�=f���}�����X��^������߲
ۛ^(���Cڟ���.�>t��Q�����y�H��|��.����;X��z�e��"������(���J��o�S<�l����D�\U��Pӷ]Fg{0bP�\��?��ϼ:����^�v��5�Lމ)�?�!����X0O��f�l�g`.z�l&�|]��F�k������yb��k�,�E׃7�tZf�1��%�
���!1����[I�?�>}4k~��nP�ve�Lݻ�;�4�{�{�x��ʤz_��WM=�R;����>c�.��QO�$�\�D������u,=����$�(��}>�yM��?m$:��ni�V���zNi��_8��
`���F�sD��7��/�J��5�VxW
�=��OmpoQ�]4(���%��T?Ϭ��n�1y�S�����ۈ}/ˬ�6��%�M���2a�H����A��LWՌ�_�}��!1L��Y��boYx�Vw(؁}��ŨF����Z�n��~o���V��Qb� a�9�p�"/bO�C���
Q�G�'��b�����������m֡��+e�C�a{�ˆ[�XH$��2g����!Yg<��p�V�=~�\�A�ٻ�
$�4���3�a̡-,���Y�������,�U��_�`�mY�1�'NZ֫jH�]����r��F�j��7˜��9,�2\�����75�M\��&��h��96�4�o�w���I�.D��I����t(�q�l� �k�9�k�x���m�n	vc��?����̓�!GM���߈�v"��a���>4�j��+��xZ]��
j���+$��x6g���у�ڡ�-�y�M��Q��B����\g���{��W7���w��N�n[Zp��v�7-�L*��1�g�jJ�VV���z�V�{�,kl����sw���}xy���X
?p�p'�	�w��L�������*�.���C�3��Ay�x���Q�����e_saM�GV��$�/�=�f���H�iԝ\9�����^�onټ�Ǡ�8��x�]��P��
/���C�n)v�M����M�����M�ET}q�a}E���G+ʏ��w��h���-���n!�kdz��s�}
�ת�f�[����L3&'�k
?
�CL�	iU��|�I?P��m�}���}E
*S'�$�#M,��K�`�D�Mij�6]�4�6�6N�\؍�̺��̉H{�-��s,�������ꧮޠS��q����J��(�Y�[^��̻8+�j��˾ֲ7�wʼ�A8l����G^����O�
���f�v�[�ȳi���7x���c�
LwP��:8#�aG�-c�)'��~��|�/a�㧡�#���w�>3�!��A�e�Оzv	�sd��ļ�B#��7�,1T[dGC/��S=J�t���5z�� ��y��iݦe�o�mIc�Ӟ���V;~�N�iŇ�����*||� g"OGP��ܚ��
'�}3F����CZv���f��z^�����ݰ��y����Mk��Ck�xm]?����C�i}\0׽u�^������o���Ucʖ�Dj�w��?>�ݜG���W����E���e�Lm�Tpqq�p��ñ�1�{3����1j5����̷���x���=�`5�a�V��ǔ���M(Úb7���:���J�|��VO>.����[���㩉�9�|p�.���3Xƨon�_/�B�b�=r-�R��7d��$���>��/�v��ƒ�C�������&q���ȟw�F��%���]d�>d�;�GV72z�t���
/.B]G��u�X�i���u�?#�(<qpu�e�+��d�H�x�n�>O�)Cb$d���9@�}��� N�Lx1��y�mi�3)�6p�3�ZҺ��1�1���'+ݜ�i4c!ی�/�U�=ql��|tF����Ͱ��ޮ�kR��ÐE���c�ޔ��y?-!�� ���~�~�34vN����Y�{��i��q���c:t<ˮ'}~���e�?�����z�)_�6Fk{��a:����}3?4�s�z���[����]�Ƹ��u��~�J����"'��[��\<�#u�#�[$$��18�Ơ\g^�	_߁[Ǥ�E�~�bPvC�3޶� ��GfK��p��R�H�~.{$��_6[=T�~m~�u�_����d��>�ǧ�,�����>��F�p�};ep��j0'�s�5���������UO����%����%���Ǔ���ތ�v��2�t#�޿s�w���̷���]������7z�b'mw.��9�_�^�G��n�����ݸ�{xt����R|8��m�%ם+Q��N���_�&u:��c�;���}�=v�
��~�B�;j1�%i�D�1��m�7���j��㫻����-B6��#L�W�-�z���
�T-���_�Pv��9V�R[/*�z++<����<�"ފV�p���uy�<5�7(�*�7��-�˗
�J2���*�$C&Y[��*��(��Dj͇,�w��I��8@��p�/��D�{r��C�+�[����|��YZ���#�T�y/�-j��Dԋ�Ԟ�y~�����3I�2��KT���{,;~~��;���	K�_�SxN��.Ի@$l����X����Cv��X����쬡b��k�*�PQ�7�S+�Z�N}Xϣ*�b�#�Td,[n1�Q+2U��,&�abM@��"�D�g��B/�F�>*-�*<U0�[P��(\|
�mz�*�׋<�x����>ZEE[^�i[���w�B����Iɒ�330�*�@I���QH�N�#��5,/��nK��!���X�����"�j\hQ����BR�v��/� 21TՂ/g��АNE���j�C�JF��R���@E#j�"�� �[���<a��,�Z���
j�(P�����e� ������_��Կ��ڼ��z��<͑�����J�?_l��
�n��R�el '�}c�YUFFNɅ����
�eN��>W�In���,U݃>��H�ƒ�V�D�-��
ϫ
;v0��i"�	�)�2�
�r�kJAn��kBg@W��
X:C��X}_@�^���
搜��37�q�9�I�F)��t-��Chh2�R:�)#M�1`� ��E���<�L5�����Y��CO��e��"#�0�yTU>�<c��[����^��&P�\p�^˶ߝЛ��Ud�52�tqV��q�V�����I��#[7�J��_a�&v�`����oySdL����U�T��k]��e�����YHgUU��+���m�y%�^���)�Kp�ʹ�6�h@C\g�>A\b��a4t�މh#hN�h+�r+kn+�B��<`a�6���v�,��@��NlTg�f�jѡ̣���d��e4ϸ�ݪK٘��p���'"\���
�&(�𧉵#��I4�&l��ɳ�j��Q��H��b�/�C��i}���-
�J�ZQFs�˼�,�0&�͠O��#"	�Sc���Ljý`PQu���T�G�
k�*�0���k�.[I�d�Q���j/��ɠm<��p�s`�oY�j-/��ʕF̀P�uDw����bL@9a���+*+4��L<怮V6�C4Xb������o�>")�$��kj�-�e*#�I�e���k[e�1H���
�j9Ҝ;"q�`�4�V4Bט������l���2��HZ�Q6.d��.h��b����0#����}|�*�Pc�;(��,n0�Ť�ɴ�H+<^gh�&@�bui�����t-A� �)Q��q�J��DY/U���V�	�sTuB�5�~Bs$8'�Qנ��+��
f�+�f��AV:�V�^D�񑣥�7*�B����2MY$4��.h"��A���g�$$��2������'S�EG�W�&i�Q�2����Z&P�����HE^�D��D��_9 �R�O�M�!P/]����T���(�2,YG9n�P�,м
H[UYUV��F;4p(JI�i��I'�t�U���-(�7U��
�#�
��#�t���q�K-D��C�L�������!��
IM��͹=�A�

�W�BR�0_P5�l^�M+�TT,[b�&��*�P�<S)$*�����-"OA�h��T�J̗�bOe/e��i����Jr���v��qj1Ѽ��uE�0*�1C	xg���Pf���� �AWA:a=.D`���ߊ���,�ƒ��m%f�ٍC������d���k���J���+�5HpT՚��6U!���^HP��Phl ���܎C�E�cD��f����BQ�y����`�y��#@"^bؘ�2��
�@Qy��� �8���i�Hf��9HpCٌ���jՃT��7, �je;�6nH��f�r�3P��Wib��W�S+�įыU��g��b�'m�ڿ�?��>?�AAbm�����������CzK:`��^w�0qô�r"��<���Eas�>���W���S@�������b<��%^��
^��!��؏S�2��0�g���e�cK�ŗ�	Ɯ!��:��1,�<(x(�[�%N�
BƘ;�I�0^�=2���P�8�����m�.%څ>.҄�h
��S ���A�#�% Gƕ5��Vq�j�V��%C9�Ĝ�'%���i[�n��&MHF��\X��ڐ�*�?��dɁ�Ϋ�c���[XC��ZȪ�2��\����\����Ȭ��ke5)2�q���6��bɁ�b�f�d���.U\�CBW7��W�HX�Cm����lUݡ\�Bm�B0Q��=�PՈ-$��)�b�*x�m�.�������Ta�&q�+�1�EC�ٻ�Ĕ�
�&��UY
�
@!<@���**rfR�ԫ�Q���"IK*
��>P���	��ȁ:�h��YPbB\�m��F"�F,��B�`�=(��	&��UjB�7���lBAG(������,��Ys�>FT񧯸m�E9�Iq��$�8h�t���ǝ4W&�E�����M����h�#��K`L[C����
�C3�n,�ja��Y�A��b�"�+�n�!jՈ��
�a
�naՏa4��k�J���Ĩ�l�
�Т�ZĊ�B����,W`��n׽����b!RIFX�M#̕CW*-s���>�s��V-Ȍ|���`I`�Fou���8�5 ��O\۩S�c�tR���d9Pk��~%�K���	��!�9�d;�S��'�o��Ll@�d!�"��T��l��ad���a3bfVID/��-�#$R��Ǹl�EѵP.X�5�S{�n�
�TG:'D�@8ݟ %$��#chW	`�=�Ѩ!��\hR2��TE�A��;�)�
Yw�b�ke�p)��XJPa���9������F���m+����P�K�9Ԛ
��>�����jGb�*��1�
u4)*}Lh���$CD)���&T%Bc���@��A+Uȴ�����,�����$�VܓDz�J��cT�<�d�Ąj�d[�.;�#���MQ�;�,	����lkAE�2sh��*E�M�H�C�X�"a�Fȋ�
~��~�I?=Q��9C'Y�"��P��Uy��$�M���g2�*G�.��AKãʎ�J##�B��4��`O�	��2EŪD塢b�h�xЗ�BB��4��l_�£(I���W�y���<1���)��
= ) ���,�U��0j�&�����E�T�'HB�����j(Uq�����oC����Uɒ�X!Ǽ��6n%N�$�I��ϔr2�/�UI`�����J$*�WF�C�@Cџ,�#O^fVy*(���eG։Ӊ�1�ႌ���/8emR��jE�'�P*���i�
řL&�Ĺq�+NE+D ��I��Z��2Xv�1�B�0D/2�ͥKV��WP��,c%+�-Ջ�=,��³G+M��1R5��r�P��y$��]�����0�dBӘ_�E��b@EXԐ��L��y���	V��gȫ)����l�>*�*����!�D��{�3�F�oV�����ʱ>��f(��Ԫ�cF�A�3�X�_QsJ�?�	1�É��P�Y����F57h�Z����VV\���kt��F��&sbTD��I�P��`�F��\@RD�P��2KD�L��#i!��|!а$���&�X[i��e��+�ՠ��'T�Հy�G )J��F��#�i��Œ�XV��ϑ2�b@�@d����Uk�p�4�ATR�Ř
Įy�!��-v?���Y����ly��aMc�^݅�/��8���It��G�
Vz���%W|�@s`̳������d�xE�eѸ��F�h)Uه#(��o��{]��}P��%iemS�b��{�g�$j�(����A��y�eD��e���z�ck�Ǿ�0zŲ�g��5j�w�Š����F��c ��������,rPEQz�Z-�b��5�"b�Ov�B�����T�� 7�5�vg{��|`�+j�*���$�
�Q��M���
w��Q�¬�e�q��4QϪ��W�9��ˑ�H|��E��E�%��J�$Fh�V��@����e���T��T���B��}��0Wd�����}ܔ�=̔�.�6���c��*p���K��ĩT���H�G�;��}�Vf����MȬ�����s���h�*HgجO`�"ZIP
t0!��:T��Y9,{����B�[0�6tA�3����8˱�%��Q��X�#�:ɻ�����G��N�P%jx>��>�c�+�6k�:x��B�b|�J�е3�Q�٨Hj�y�JG�}�������xξ�`O뢊>�\$w	���r��a���N�MO����1�	ag.a�i��(d�δX�A�`���#'n�
Xf����k�Q����E<,+�T E�ڡ\�������cv$�I�y`k0I���Θ{���hi�Dd�
��Շ�P"�C/�1d�e2b3�i-��A;$�1+M�&��ش�f��nr�eĘj,ȅ�*L��"	D�4uؙ��,@�1�Qz�0�䉕�s:��q�XͰa쪻�8�N5~(��2SĴ�%	e�܁T��N$�!��xhhp\�L	���P�`�/�@V���7�)�A��Ϻ�<�,<m���*���z��u	�����ch�ܦCsA�������
��!�
q�(�yz�*J����ª��a��@�����)��6(�Ɓ�0{�#�YG�W�h�6Rcq�����Ni�%��Yh�ES0F��Q`�x]��4}Uӕ�{#�g9�C�Q5��������	uc
���6�d�Ƈ���q��t-@�Â���Jȱ���UQ1(��Z��;��j�J}j,Xne����J��b��bWa�wr��͗���QZ���Oo��Y�|Xf����:�K��w��w0$p،w��D��Y�
#Y�i��4)�3Ҍ�$��e�����@+YE�(��Ù�2�� ���7V`L���aʑ�]�0���0�ޤq�G��Ŀ��e�v({:�йRER��c�[~�p�6h�LP���A���{����S�E��O0�����aT�%I��$����`f���!�����+lN`Z�北��jQ&\��e@�%�
qP卨S%;�J�t
PW�v��Ҩ[<��RY��%N^A�)�u"
*Q�T�5!8>�X�5bjB�Q�J0�A0!#U�/�ІE�$Z@tȫ �ׂ�VB�ܵOVY�"!��Ԥ@@f�J�d٤g�B�"�A�h]��]��\��	f��MĉI�S%>�G�z���D�p�YB�q��И+u���"V0��"S��f*�^U�,EQIJ�?p��A�t�t�@�����A��dҋ�J�Z4�Q��54���jx��l<c�0䌶i��Ɖ��ob1Q"1Y4�$��F!.�W�x�.d5ǂ'�rj`�[���uP7��LN	M�:��7�ZŤ�k�V,z��ܫM��VV�ux����yP�s�rAW�β&�AaE+���0�4��6[9k�P*jO���F+e�(;/0�֡fj��Jb�_��D�0���Cf�bPS�QE�1y�AQ�3�"������.4�q�*D]W�BڀYNc�9=K��;j�K�bw�?;�AvA`U��Ob�c�3d�~"��
%Y!A�i�J(� �# ���Bn~��MD��h�%sz ������ؾz<��h&�5�6����/7�@|�`��S�-dy:�?��ZYR&0�-b��B6ɩՕY����m^԰�Q"�L�DC
�†`��k$R��Q*A�OJXHr���UQ$���0o���,BPUi�Ył2)[��Nǥ�3T�+��d%<[3J9�Y�0�&I��n�&{��n*[�H�T"��E"�r_+{���7
�Y7�#"�����^�!�l^C8h�'p��JpA$y���2���t.���j⭢3&P�I�#�y�O�4~����AG��%Tt��y�	`U��iuZ`��dA������D�s���\�rIBi((�E��L���͢��t]��<��
Y��z+�P����@�'��',{-Wz@�݉�T�#U�+dw����'�0�N���dF0�g�+dHY<ty���4���9�V��\i:Ă��Հm�Xs�F���W F��?\Z��f,��ۅ����\�����\�������1���D{���~-)��k��k}9��:��:���������W;�\�\�\�\�\�\?�
�j꼥8o����.|༥��yK���oK�!�u^�u^�u^��wv��d8���깷���/z���}��:���u`R��������ׁ�ׁ�ׁi���;������x�v�v����1��������������y�8/��y��y�>p^*�wp��k�w�w�w���ޱq^M�ߟW��W��W��W��W��W�1��ή&;����ˊ��y{�����#}^p6vz^pv^pv^p����/8;���h�h�>�h�h�h�hj��h������MqU
endstream
endobj

10 0 obj
11976
endobj

12 0 obj
<</Length 13 0 R/Filter/FlateDecode>>
stream
x��}K�$9��=~E����M��*�,��J
�0�M
=v/��E��A��="��z��	4:Qd�I���fdn���?.����l���/��W_�K��f�����������\��������_��^�z����������k�_�r��?����>��_.n+����������|�O��K�]���O����GW>}��O��s�����.�?3u�߻�q���}t�S����1���y��ۧ~�5��������/�95��P_�5����\x���G|;.���x�G}o����#3Z>Ԏ����}�:J�ǎ������E_��f�1c�站\?n�S���-K$:�r�����a"��)@e^h��;��Q�}(Cܖ���
@���.��&���@��#����"����\^�1�������Ge�4N�7�.py=��z�|���(������}&gH옭gT�a���l�F��ecү4_2�|�]�;��șhn�oG���A%o
c�+t�7���
\wdl`�A��}�օL��a���h=_e�=��m�-g���N���l�Q;��F�o�eQU��X�_v��;���a�n��q -ˌ�c��WH�w�-*�'�Ć?�#%O����hHB"MG�ٰ�-�b��BM*�\U��&x�/�`{
�r����Ԍ#��t0CSٹ���܀ʽTU��~|hk{�y6�?�^7͆�FR�o�ueRL�V��~�ե�ď�R>I���,�TXԨN�}e��<Q���J�̙�<��}U��Xn��od��&�����9�ˀm�]lX%!d'�ɨ{�-�k���1�������!\�E��|4���N�̈8�~�.�Q6������Fc��CL�z`�X8��&�F4�}쮍��7��!�1hP�l�}5��
�XƳ��E�}4t�;�_�Z?�R_ˣ�l&W��֙�]�9��t�p�sS�u#��
e���j<]z��L�G��u�)gt1s��7��fD���j��~ä��X�{l���oj[�i�<���m�Â9v_�U��@�Nf�dR퓺��S���1�ES:�?.`�޶R��뢓��y+�߂anL�!�)�x�b��lo��Ie2�خ�w���TE����{�|`Ƴ�����o�;�M3;�NC;��?������{qz`�i�6N�W����W��M�cֽ����;��`vZ�ݘ=X0��fW�E�;��E�P�C�����P��0ο<��y�������ު�oyZ�"{{g�����"��5ؕd�L_UKC+���bQ�����+S��ۃ��N�Z�8su5�&�٣��og5�ddN��ez1��Suyx{���E�KA7
�������1�����4�%�q܁���#�On�87�:w�C�m6b�S�d��m��H0�|�_�)|��)^�N���d��(v�?�*����}/���)6��y���ջS���ȳ��rP��IB�S�"M�Ψ��������w1>Dۏ�w7����p�k�����r�2��-9�AP��*���O5M��ß{�8��}��$gؽ�:ӣE�7�U�04DZO!�`
t�
r䩦�ipw�������F�6��&�'���F��OZ��`Y�́A�S8p	SgW����ۘ,�a�qq ��N@%��X�T�<��β��֮�
z.��pQC�[y�?y̎��<)�`ؓ j��HIA�w0�|^W���T��<r��4���D#������:�Z���k
>��:o>�n�ⓢx'�S��R
?�xC� �7���!

��쐏ƌȿ��m�(��F��r�n�-��zt��2#��Ƥ�X�/�7suJ��v�����j�k@n�%����Dc@MH�;�/}6�<��K��˂#����YJƳ1
����2-�ţ_�0bN����Z��n��G�B�cS@�E�'n�{L��m�A���4'2k�J[�*&��D�x��\|
�uvYq��f��k?=��s�}
)�ŝǙS�î/?5�w?xW��M(��9�&z~��)�}��(�RI<�i2�-=:,�Ǥ�gy���
±թ�H����]5碎����
��2�;�ؙ��Pݨ���Ҥ��o�:Q��b�Rw�֓ZYSu��o��&
v�Cձ���5��,�@�w/�,}�m傝&Z��J�I�X�偸?�k���k	n����{��.�����$��W�s؎��}c�����<�^u[]��Ց����*�N�X#oR�����rBK�aB(��`��=6n��7xSw�4��§;������&�y�w�%�ϳ`��#
�U��yaΝa摽y���6ݺ�a���T$1ȣH����5)%�A�#�0J�F��)&$��Z���!Q���i9�l�^Y�?P;�ь�m��3.�T�d!	&0�Qxa����‚�t����dt�����^�d�ʗN�����!vw�@�q$�J?���w{�+�eP���i�d�ښTL֛��GS��
a�9�}�[��#?]Ş�S��,�+�cg�x�k�C<e���=�Ĝ:dM|z�
:��f�y�G�<�I��{"�,7>O���* �U`w�`���&������=%d�4�r
e�'�=�ZZ��?�.��s�[νM2�G�J�I=����;+�g��N\��O��̙5�A8?���f�]+�Q���r
-<��㪉���g<�뱔C,Z�:
�'���Y�a9��g���0#9��T���\�f�G>�_ni���{�/��&)�=��Sǩ�u�u?����b퉙}Ӡ]V�q]�?�\��?��W��-��Q#���=��sK�o�Z��o��3`@�s$~�L���a�����s��Ѹq?��2������T����r�̫Hq
�޺s9^H��Xh.����͵8���uv�t1�)pۆ�-�J2�k�+��j/э3n��'�c �y��at���	�Ν���(����+�O�v�q$�%���|��֩ާ���ȧ�� �I�,����1v�Q�:�w̙�(s����X�����!�c��`�ҁl��v5	Y���c�6�S*i��U5b���;��29�Rt	SPd1˩��$�u����v����׻�,�H���X�ڙ�wB�H��Os�k��N�-h�ҽc�/�Ā+�N�J2����*�\�M��b�2�v�o2����	�:�G������oԪ��w�jF��&V���-�D��a=phd1Xnr67��Q�d�x�Wv�ꓥ0��
ٙ�M���-��wr��t��w�Y5ͤF�B��;���q��'}���ž����(�R�h�'�K���$��D#	A�2�T<�萶=��s�;{�͇X�x����Y�����,:��*D��ve(W�0���a���Z/>
iȿ��C��ߑ��@+�uw�=N�B�S��Q���Q���;a��J��Y��~������z�>�?E1ؽ�z�87���]A���wΟW*�;A��#���rX�+i��{Z��,������J�M.�A��k��;0�LXK��ٿ���Ω�g
�JI����1ɏ�་�J�\f��~��3���!�tKC�&Ώ��G�M�V/S�QD��a�������x]��g �Bx�=Y����B����*���
���t�m�����R>���8�o]V��8�k�+n��x�.I%3��}�u���0'݆+o'�F��V����!?�rJ*ҷ��i@��+��2�Se�}ݶ�&Lf��d
~�uT�L�qG?�8�:��V�[>�6J���
9�u�
53���"n����E眛�������hd�(��T/��^�@�,G7>f�k$	E���c�2eD.;�sT����Q��up������F]g�#Kozus��>O�]_�p3[LՉW��|z��a���whf���ӥ��g��b��V���%��XN�3S&e�$nx�>∦r�l�5��	��?������/C�U��e2�kx㞀c���x1�y�W�>�/�,�+���0����%U�~�b���#r�y�j8*s�k�=���!#�he�.�Jw��H�?����	�)�M�n����+��w�I,C�?����+��0����wz�*���d������8�������ȝ�HS��a��À�{?s�i|(7�Lm�d}�S��v�D�]���p�h��{�O�6�c�ktn�ؿ�=,/f�wV�W�@􈁽�Ti"��x9���a:=�{u�|BȽ��?�/�珖�X���>�<�^���v�`X�CwC����*���i܍�Y��G��=Z���p�E��? �珎cL�R[�>d�op_=6a9�_֯��A;?����p�Qr��s�-�����y�Ӛ�ₓYpX���݈�!���!�ܷ��qzhܣ�믗�^���_��;"���[�&�X�Uy
t�I}�������χLR�L�.����I��0ϝMS�IG�k����9���v�S��>�S���R�V���oD�[
(������ez�/����ÑYs]�x��Jy��ε�ް
�G�V�z�W����6X�m��뺒(EP�'���%���K[h6���Rp�ηi+����KyK���?��M�s\���ٛN�>?>��Ԟ�Gc��D�S=�T��\����rM�w��o�ޏ��*��i1Y�Xr�f�y����J�7��Jp��a�d<�r<�5���J����g<�«;��9��;e��ė4Dcq�l�I�/t�P�[������t�4�1�ʟ�?=_q�qۧ,�H}�(+�>��;ϯ�ٯޠ&:��{��yfo�eN�Ҙ��(4�{DH/�IU4\=�-���o���m)N5}�tZ&'�>(�E�Z�.���y�
�8���	��v^
k�W}�G>ˮ�����F��l}���
)ؼzE6��o�W��|��ۛV-7�` wG-�PnA����p��okr����``�VDw�{�%>I�F0eOiӫ��~Н~Y}�KO�WK/�{۟��Q��7) ���S#}�x�+���1��G�Z��6��S'���5e����#�?>4۠��_ֿe�[��S��q�A��ӊ��?Bd�w�wO<|r�2U�����b�
��/
��&wHB�
As%�{l�ʁ(
y��:��`�9rɦ\��=_L2m�'���1<��8��w���LO����Y���cWI���r���'�����2���;۠�u�� Ό���@�DZ��Lx�Kcޕ�'����\���9h2	�}e��(�����M��i���fN�=�j�zq`o�l/l���ٷ��8~:��#��c �H�X�#Cc��+�X���%ȴ�z;!D��){�:H�b�w�2j�0�F�~����>�f�U�}b*��^[L[�[h������Q#�-��C��wսƗ��k��uT����5���R�'tq����jIo��Z:��z/ԑ�#�Ơ#u��j�;�����K^l?�9}.�,�g0z��Q�^H��68�Aו۴���U� � %ʞ��>},�~��y���0��"���M:2�g������o|�ﱁPt��אp.��
A��2�U�@�7���|�k��|.�
��2_D�w"�}掋��iQ���@��q��|�2������ܰ��g��V_CBG��@�r��(��{�nc�"�=��ꦎ���Ή7A�mY���ʌ�gLr.�Q�v2c��:
w��\ƔY��
`(�ƹ��Wy�վ��F�úPG�Au� L��6Z_������z�^��f�Q^�w(���ⶂ�6��^�2��2dCKa,B�@u�	��h��$�6���lM�����-���ٚ�
_T�S�c+�EH�l4O䐌^�
�IDU����db�.��Xr5��`��)�6^ ��r	&t�Lؾm�z�5�V
�2e�<�$:x�j��_�
����Tv%Y����/$��~��T����ue�#�ގ��4,���r�'���J�t���X+��d]���`(�TF��*��+[���?��L'�p�޶�C�m��"��D��6`b��wK�ʯH�f�݌`oD�#c��=K��u�&+$��M������`m
�^��?&p�t��,��B<F�&iE{�^Y�S�.����Z��T�t�u�Heѐ6�2�1P�"i�#��z�>80���gbTQ��(�.�E�n*K�gE�G�_��
YA"{L�����QG0d
��o����X]*P<�Ј!A��}Q�:xg0�ә���8��.�@�]N*&Ys8��b�z,�6=n~%�K�:��-�"iX�����}do�,��,̌����� &��|"s�y��������-�9�i�9�j���n�6��dk6�j6�N�;3nT��`t&�r�g�x��G8�p���Y��*,	����N�X�AE/$�(���A�LV�"�NxXu���eO]n6֡qf�E�/g0�c���ڳx2ܙM$ib�n�Пb�f���"3,��lBS��:�l�K[���6��}�m�'��H���9�1��E��f�}W~/I�X� �ʳxvlD�7ud�=M׆u�[J�[F�9�O�L}�V6h;
�d�8�.�E0F�[Q7�.E�!�/�n����]xr0 �u�����3�ˆ�\	Q�Ds�(�!0G�Ze�҆�ț��#7���C�GbE��s���Ԯ]�6N���� g�t�)�
r	��鬝xO";��!�i��)^S^��	�ldz������ZW�lb��;�u�io툶�\�DcJ[�>�sG	�fL�u���%"��L:&6-�.��>C5�!�$�Ύ6�Ռe�k�63LM�������^��
�����s4sB"�-�~�9�W��Mst}-طLX2�a��"0KԓάJP��x���yK����2�Y��ƯJ3�`!"
�X�:��wA$!�EV���2e27�(�,��S2�I���d����&��!���P�B��Kf��">
�ב���M�!p�]֐��T���(A�$9��7w��!,`��!X[5=6��:��vh�P��>���d��C%O6����k;�O�v��p6Q�d�s`�&K�+&O�����%v�b�x"��٩���nh�A��V�"��):#��s:�e���현:��:�7��!4��0�SS��4C�AS�!B�w$�6�q��e������{k���3&��OD�kGIˌ�����t�T0S�h������n����A��]V�D���O�Ug�,�J����-!�ٝB�
԰�d�6̈́����1}6
a�
�x���,��Y�M3��D���(�SDž04O�g(w3|�F��0�.D7�V���m�>�
-�u����q�����p%���r��A�9dӵ]�&6�T�1C�*fT�UO\M�oH��Ѭl�a��l�o��_/!,b��q��r!�u�R
��RP��TD�K��iTk�B�0Q{R�����k#z$��jG�Ǩ<�}	�CW K��%��>����&��vf��>��۪�e�P ���P��X�d(��+/≽���VxS�Z�j?"��6�0{�ڄIڲ�K����Y�y�D���bh�)xj�}Ꚗ&!#�6s��XQ���S���0��%5�8$���ɛ )L��Gd4faK�'��m8�X"���6P��D|��8E.TlJc���~.���$M̛1*�{�$�˽mʷ�$r_�8��u�l/�X,�K|o[F�������*�Tu�������u�]�3��fRH��#���kT��D� �=Z(��%]
T\ �Ս��MJd��"E�oP�����;Tw�
\YL4�vO%�563b+�u�&C%��7aRGP�W֫-Lr�p�3��O��b
O�����X�1Q6?)�"�����*	Z
��B�B�RGef�O�zMeT`t�f��%��I�j�жL�r6I��:zk�,j	".�u0	#�X#��d"B0i
"&��(��j�Q�5	Em@���/�$%j;f?��ϐ�����M&�v�I��g]�Mnz�DV��P���I#v4;8�ğ��6)�K�cwD>Tp��ꮛ�W���ͳWa`������A����"#�+�a�AjUӈ�V�Ѱ�nՏq6��[[ZU�W�٨o���hy����Q�i2���m5����/v��N�#@*���-��">t&��E���"uD>�f3D��
Hۥ�mgd��?<�T�0���e%����"����	L�;Θ�����D&;�Y�o1��b//>S��ɼ��)�P�O^�؉�%��gEM ��2�ND4��
df1N��@�c�ّ�)!v�hcx�U�<�Om�yp�Q��K�p+u�z�91�@�,��VB�q	H��k����B�0nf����+oJ��2��T�t��kic����m.G9Ҧ�ul�!��9���'�L����v�m�&E��H(E��tК&x�=�7��v��NL�M�ȘS�9����,�z�DpI�ӿ�#:9���%�%tD��ܡ�*jr��'�|Z�&�H19��'��fӘQ@T��Vvh	��C��VȲ��d>�7���^�
Y�EMkQGA[(4�Yժ�&#R�;F�m��`/2@Ŀ�u�����9��):��2"̆B�r�W��˔��R[~_�@j�� ��G#P�ge����4>M�2ٓH��-�pT�iT�:��VhL��.ZbS�iM!�f��SP�
�^��	ޕ}"�K�=0!��*Ѐ!�SGQ�*'�0f�f�g�rv�y��E$AJq�,����j8���a�g�C��n�K&�*;�M��H%LNe��[U�Av�5X#h�*�ةlyP��}�؟�����搉���O��Q`/�?Up�eZ���:�q6F$\P`���d>�Fڬ�����#�b����h��ə�&�ƹ��JKG�eH�~��bV/���(�?HC�����:�c���'����؊K���^L<Xi*���	���u�j�y��ٳ�7�T&!WL�Ĭ��|�D
:c�"�fHQy&{�3���D�d�S�(����TMbP��	����J��n��@�2�|�ި��F����
�e-�4�GК����1b�����$)��da�1N�{$���ʆ��jSw���Q(4��&�(����i�Ht�bNTQGRqQ�HD$�4y��"P��QH/&�i��?a�I���9�,-``�I#��L������hP�A�1O��uiD 9J��ŦS���lN
��e���tY��=r�R�M#��X�ƨN
ge�ƒ�]�T(v-�Mŭ����ᄮ�.���߯�7����.d|`L�q��S�F`�=P��S�������Eރ�<�i4O�O@��+2�ŅP���@WY�j�}����'�h<,�h�����mF�ҥ�"���Ψ$��&�j֨=�<�6$OA[�gCk���<b�X�*�7��=�[�*�Ȣɵ�a�o�ƛ��dO�T��G79Bt��e��Z�bҨ��t"j�/vL!*�I��T���6�%Yvg��V�|(㕬\U�{�ɦdTd��X��Cᎈ���JUF����Qm���rJ�
�$m ?��d�d�ѸC�D��pUe�/h��
m]���ґ��u�uD�}�5�8��;��{x��5��N9wa�A65���u`�R��Yl�Tn��k��y��|��{[l�K��-KN�
��!�dig�v��u�+6���2�g���ؤ�v���m�F�"j̰��i	>�>�$Qک*�e�r3�Lh��f��]Q�z�G'��N�P%4<3Be�����{����&o�fHA���X"�L�m�|1*�p����b�+�Sz�2X�%oA�/��K4��T�D쮡��a+'
��dMz"5Hc
&rRf.�-����
�ҙm��t�rv�8���hD[(8DA��]�*��棨�����h��~V�YqL��'��I���(�`� /�#v,+D�z�#>Z�2�g#���|�q��a(��l��=�g�_G[���b8�LKVLS�~VA�l(G�eBL5U
�Rt��XmK��i�:e&	+�� !&a!.ϝ����QN�=a:3e��L	"W˒R����q�HZJFL	e7)i
Nm��	U`�lGh�
�k�?����(P�`b�2�A S�~�).1��o�G���7�>����d���
	�dG�y
������w.sz�V��~�PfU���m��'��C�c�fR����M�����D:(Y-j�2v��hR4MT�����,fW^�jQLN���M�RYP���}֤�fe��� DF��Q(]H����5}3ӕ�³���hV]R�FGp���ܘ
�6
��ʛ���(oޢT(�"i�,j[ư6��~.heg
�!(��Y�Ȏeg��VFVz[#��k��k��ɯ���U(��~X��|��<�eP�a��<4g3�!�-��@��%��<�;[�kؔ2��M��1��DH�च,���?q^o�)� ���'ٔ�8�A%�,j��tbV�G��
�T�^DLy6�[�v��$Z�ܛ-��p�*��hWk3j؁���qG6�/�=,?��
>�-�m��ATy@9���Q�4�5�ћ��"���[���	�M8�ݖyc�_�uX�c��3_02N@��9�f$�=�de�Fk�Ա,�u���_$�*��MK%hQu�lwΖ&K�D�ZD���V�s�	�L�kP�^�����	�S���4A�	�	9%�+i�\�AAFn�/�І2.(:G�5�ār�����	���)7 ";-M�,�6�R�X6�ݰؒ�`�/��[�%�<��B�$�i!YԐ��y��c��4���
HB�
8A4jE�e	�.J�EfZ'��OV��\w�.UQiI��C�`_�i�|�{`�!�������3nJQ\�5MP*Z�5\k��Ϩ"�@.�M[Pi�YQ����&�OdA��
��(��3���ba�7s,�/o6S��>�|�A�$�3{C4���v���jkhE�/98��=�y0��bs�m�K��mz��h��Y�E;Y�˚-���6ͥL!�E��]lFjU�'Y���+
r��m�/h��벲�� �B:T��v�l*E3�=w$�)�J杅��N�r�
-a1��u��n��9�UNsԜݥ��O(-�?���L�vkP\�CS�l���Ջ����|"�͘���h�<[%\�H"T" ��gL�&z�MH�!`�ecsPT��A#�7�����D��a��0���x�HN��18Eoҷ����������L��-�Ca��M�fu�ʖ�V7Qb�4@Mٸ�3�0-�J	��d�H
��q)A�O.X�z��B«�%����o��0�]�h.Ti�]�
�Ԕm��q9�I�m�!'�`�[����\N̅�p*h�V?�v3�X4�����K���4$�h�6�Q9�0��v�-X|��-�9B�Xf�X���vf����d�����ڌ�+$���z�\��#��q�
 fD��j;f�������
J�?�!�C4��_R��i��W� R5*��1����vD��Eu&d��B=��J2�UI�������gB�������
ւy�L
k9�V2Ki���#�L~E���n<@�ݫ���w�'lw���ዼش��{6#D��+���~R� ��,�α3o�4ބ�Xa�8�V���{�i�*xg�B1�?�ӥϰ�֍���y���˿���/��?������N�[[r/��������k=��������}���Z��}���<o���\�'��Op=��z>��|�����j��J<_钎�+]�W�0��Jׯ�W�L���_�zHw=�z>��|���!�G$�����|������/�|������,~>�����9�_�ρ=�{>f���#��b��H�Þ/�=_�C��� {>*�|T�����Q���GŬ�|T���<�xT�k�����ݱ�c���= !�O���ϧɞO�=�&{>M�|���4���i�Gt�����B��z����G���ټ���g��~}>p�8{D
?�@{�����|����
��hf��7�H�����r
endstream
endobj

13 0 obj
12239
endobj

15 0 obj
<</Length 16 0 R/Filter/FlateDecode>>
stream
x��]K�$�m�ׯ���m��,螞 ���`�d[�Y�E���GdvWWU56�Ъ��d���
�������9<�4�uև��y��0Z<��N�������������������^X��gE�c��=���t��odt���?�p��=�s��a�y��?����Ό����}x�T��S��O���}ztD�Կ��J�~��D�><��I����;}$�k��km��'����w�����]��	?OB��b2v�[X�g�
e�@�����d�c<�c���(W���1��eԭ�ʧ8��IJ%�E~^�-}�4ުL�Eg;7@/~�<?5a��Ǎ�h��|��?��{1���G���״%���V	�͍p��Ghq7�E�I{��vl�7
�%a��������_v���[!�]Vi3
�*,�(�����~6% 8R�|teA�q�#J��igefU;J�F�Jm��n\�)���h������h�).�n�u@cтu��ka��pBkz_�Ӭq/� _�x2�n,�Y����N��G�a2����Ά��q!,v+X�����2���^�K������7^��I=�#�}z��Dy<��N$�yc�}Y�w��y�
>e��<�l"-s���k"~b.��v�Q�9-��b.�9A
���䱬W�hL��%��/��8�FI�'���I�l��9A,��r���C�����]fY�6^`&��+�W�����G3�r!����y��.�x'��=��`�l�`���lVwHq���w�
�R���rk���`�^7�I���������	����a��!�7�.C�p�l�$�Z�O�j��&[ZS�E�N=���W��n&ekW���y)������M��,��U�8�ٵ����T�Rh�)_x�&_YU}�QsLb����х���������G����%-*�������_��9�*�Z���,%ef"ρ����"��p�-��Q�eUՊD1�ŝo8����78$�+��� �@ �e^k2�E%�.��bk�ߌU�F�ђ��%i0X/!g�BM;.d~���}�8����[�(k�X��._�\EV�k՘��U����ɴ�q��~��Z��S���ђ�
h3�&��#�n8ڈ���!D�j�5���U5�Hy�o&~��{W�-{�N���<E�����-"ߌPu��h*�����R
�^�h{��B%��B��w�_���S�����
��<ķd_�F����%�S�S��ԍ�3U���CyC�)FQ�R�D�
����LI��z�)��q���Dp&>UK�9~�n��j��&���}�/��Q��pq*Vߪ"�Ģ��SN��d�jj!�$��,��\*~$��)D����u|I=�4n��3]R�[��ŧ����
ң�,��W����I��*I �N����I�5�
�2���}����N���g!8Ԗ/N���K9>�5��.��β0H�U�;^>}�PW�%�I��s�Bq�̍����ib�×��^��������<��h�_��L��<7���s���/:��\��57
45w��g�/�1i�4Ȉ%�L��0O�1?R�%^�	��$��w�s2�'����Iس�Er����-���?3)2v����B�H�Bꡑ�^�wg���%>fzV��:���a���S�!��?�ᷧ�
�y��L������/o4\y�{~�91�S��S����&.���q��8�x��K��<���]ƙ�ܛx���냍K�h
v/��b�Y<?�K�_?o�ߤ���%���@X���
��\�#��*�te�$���S�1����C�|U!K��ʗ�����B���4��>.Q�W���D�2�~�R�T��+�b���k�3^/k��B�߅B|�FG��<HC��_��W��s^U��͕��ny2Նo���Q���b�I/�u�T^S�K�n)z��_H&Wl��m,S�xM]�H��8@E�Մ��g����<�^U�V��e�ݲ�q5y}*���N�9�I�#R� ,xu�Ua�~��L�9�3y[��3?a{�S�u�j�F&Nz���f'�&�o�`��ܹ�ف��0����N_#���x^�~l!��q�m�u��1^uTW�F��ݮ��> ��F����xs�&�Mm��繝��Q�����h�)��Az�-�hkwm	=����9�[-��ۥ�������ls���Z��zn�8�r�1u�
�J�$�G;�)���Z�8��R�~��x�S�^�d�I��,?�W�B�ָM>�K����'*ޮ�nw��”�/(�[���fߠOǸ�����C���{�-\Z���Ǟ/-I�w�c��x��L�4�.q,��T���ėY��w�m؟�%~G÷�1����1��Fw��t{W�t������{y�_m2ܻ���>�J�x^�^>*�(��S~^��_�m�e��
���(?�A�.UCW�BZ}X�Z�7P�i��R�tM&)�>�!wm��� �hZ(R��g��Z���@顎A��@E��\�Cŧ2\O4��C��0�
k�:BA}>�
>�91�1�"E�'���#� �B\dȓ? {�7$	��-K;��I��6�� -RA��en����M����2CID��A�d�7���`)]	�_���MQ��D�/����(�J�n)��^)�U!0Z~*�l��Y�(���#;��e^(G�S�PY��"�� N)*5�,�YN�Bn���ޘ�d��Bg�r�Wj�!W ��>�r�i�Bd��CQ�Ј�"7�3#����D�2E�܍AyO�J�Ū�ˆ8*�jTGtA�`��d3=�6�چ�M4���C�Ɛ1�L։Y�jB�&rpAǃLwX� 0��H:�N!��2!4�y�v�܂�묗lN�R���0���0bl4	���H܄��C1���AMA6��AJS�f��Ҧn��mFV��<�Cu{	�IC�x���4v�t�r��#����)4��Rj���|���c��7�J�V�Sh�Bax���ǰ@2^#��]UG������Sٍ�����l�l���d��Gp�K�ҟN�u���RR��^Lkz��!e�2:,�
���M��2��9I�!��az/��J��	{E�^D'4�F��
��:ۉUM�N7�,��}4�i�Kd��F�:BU��`�FS��`����A����A ��	�M���}��n��В�D
b��s)Kj��R��Z��	���2�1H�i(��I�N����J/��P��P���J�(�5��Y�v��bDG��藑�r3��n��5pdO�YI����<����Qҥ1%$WF$DG�1�xL5��!g��E�0��lz3̚�iR2G��y�zAaQ��&�^�x��䍱�dbBT��8y6��eqF���)4+£��W���WF��a�m�w��I�hˀA�.B�$L�8h�����Ƣ���pJ*�6�T!�/�<�@d6cu����	<[�du�V�u"i]=Zy�
ey[_ ϔ��Ѽc�WU�&�Xe��9%�*�MW�^kp�(��+vN��O���4����kp8#j����j���PQ��$���=�NG�m���N�	���D1l�	ɴ ��+��/�yqLr#�Mgb�p8�/
��da��|�B��0��k�� ��-fcjXB����R_�U
Z=�A��ɦh����޺-c�������)\k@(po�"����HVL0��#Ҽ����fB��gC��V6B
�4�T	mZ�U��&�>!����)QZH�ృap��ߕ��i2�b#�<T�vb2:\E&�UqV�V͊��J�=i|�(fI��a5�'U��F�*q�ggz��)��z�Yj�1�������:�ؼ�Q�]*&��UJ��A�/�D�}j�8�XV���$�aFu�2�jt�L����6���j�Țc�"�H-1��'�#%%��xu.��M�Cn%����`
���L7�
=�K�%�z}c�)п�>W�L� )~-�1B��&`v��3P�h^y� �sؑ��bK��s���Ia�Zs�d�^h���0aDB�Vsj�#5ټ4���!�Z���z�}Ahl�� tꚵĻ��P�D����$�|�#�E�ŕ,Pޖ$[M�	6�����uh�V������$\����SJ��te�<�S�M�z��+�F9ʈ,�z��t��YHSb�(]��O�w:��0M�O4/=ɚ;=P�@����4��E�RS�n�ShF[�0b�bB�5�,Ǧ��j3���Bs��)Fh%DD�'� �.''D��`�=9<L�>o�W��=���&r7��ܰe�/�b����H̰Z�"���d?X�͘��z�b���:�Y�9���%HM��Ev�1۬���d18s��k�pl��Z9`->�}"(�hz5?%�L�SJFdS�� N��-��,DWyܲ ��x�]����v#�ik������K�U�S<xð����Q{v�g^8�๖�l����8$/C���0}��٫���6�^e���4O|{�+�X�<씾
�}����UJ��S�V�p��p{�%���O����^A�x��aS~eh�c�c1������zyIί��,xP]2�D3"'[�V��;C(�����\\T�E�2�� �#Ӌ~"��/�R���<�e)��`*�Q��YN�'XV���ɷ�%�%��D`Xs�	=�*B�ϰrH�G�!�����;`�8��1�j-a	��	6�x�CZ�k\�D���S�@����"jl�9:f6X�mD��x�;,�Xb?�b���^����e�=�ISZpG{oن�z�`O����,��"^�����ۿ\��;�h�{�����%#��>0�I͋9�����F\I�Q�b�ET�G;w���M��7KX��+/�
�U�hA����UmӗC}
�k�!aB7�y*x�Z��C�z&���3B�&�\f6�ɫ3o�tD��$m^��t!j�F��v�QδI6]9�d���h������@�eĄe6�O�z�bTu��D���
����ڶ��8[�Q��V�bHq�G(��u��r��A!�T�5BL!a�#�C���C�g�J
p�(��4$���ZZ�ڭUKFIrE�D�f�B�]���������'�g��M�K�b���g���n�����jpPs*�ԁ��b��2F�+�2V��5<#ʶ*#4��ݡ�	e[0o�Ϲ��ҷY�h�o"��*Z�`S�U �;M\N���*�����}����B�8�ω
'���)��Ȉ"�<�B\�������^Av�M�q��J���>:���-�g��9Y�vig`1��s"鴵N⒝���e<�=�)a��~f���,R|���@�C�Y}Mf�Q��,h�j��=��F�$F�MQ<|Ď����J�±+EY�따���|�
����52`�y0�E��,�VF��&�9�z@*����q��َ���X���1x!�g��eL
}`zT��^�gi�� �ݏ@$��•.G
V)1"BC17r�^��C�G���H�g�Z���P-�9dM�x�����K�*F?��sF�BS���X<�"�
d,�K���I����J s��4�Z�@G4A�X�J��*��̛��Ƥ�і'M�洞QFW�ae�E@�(Z��j+��J˛�uw�/k���mk1�Vm2WcX�ih�[����b�wd	�>��_։����h�b`3H7���!��
=ʭ\SW��2��w)��v�N�Ԑ�Q�z����HGV�֟f�o�Il�ֈԥ+6�+ψ	x�����qm3���tD�+	>�¾7�r�wUN�ٹ��
ƒ�ؐ�!��O��VY�*�ֆx�RÞ]���}��dǬf��(JMLش�a�ėu�:��KƆ,̧moc+a�h�����aΠ�ʙ��
�jv�T|V�_���*�m�5|A��F�?��GYV���i��}���$�Ir���vAG�f�6#�BrӖ�ܣ#�<MS�*��F�7<�t)	�ύͯ�CG�C��;��^���Nn1�B]aH^ȴ67
Q�������uJ���)cz��Q�Y�F2fEz���6���5�WqϾ�
�a}x3	m��A�4+����!F6��px!��3e5�<K��MTg�D�*e�UͰM�?M5�l��]�rCj�2W�P�9�?�ը��� s���d��4ˊ`N_>v��Y#J��+2'G)[Ov�k��z��Pq����a�~6�u�����&���%�k�l]Љ�~�'�Q-rd�2Q�*���U��R���ϴ�IԴ&�Kĺ:i��:}�[v�A���^[ao�~0�a�=�
�k/����pN���ti�~O�U�{�bdN�[��|���ͮ��%��T�����i�2�����\y;C��q=�]�d��V��a�pV�v��;~�W�l,VX�1�r��w�$�>E�.��a{�ޠФgKѲ���5Q4�E�H����ݒ���dZ�/�3��*�H��'k���zCf>��$T��7O	�NG�j�"��b�q���jR���ά1���.��6�	�V�=o�������l����w�
��x\+���7���$_1�ٳ{d�l�%nB<��e��f�Z*�b����<#V����B|H7N���l�zu'�2�W>��U�����ڬ�͛QE��i-!
��.��l�ʧ�2�h
��YS�	�Wb9}�pU���)�?W�,#� �$:�5��0�	�
��mHI;D� N��'�ȱ���a�肘J���[�|o$���
vSs]�;1���^��K8G�I�K������~�����q�VW`�Me��v�h����\hO�wQ�P-�aB��uFE�T	pv�S]SԢ��f��-2��I��u��5H�&+ີ�d�ب�T�l�4'I�^��2�s���^+�5���j�)�l�w�Vv�¶�|-*�p����{�{g����J����@�������,����KB�\�aHi�4���� #	1ro��\��ΰ�f	��3#`��9��]F(n�y{�V�Eՠs'7�������0��`5��o�V�$���C�9q�f��h5ج��{��k=֑L-���g��a�J�<,�o_MK�����?P���:)bK~��T�~~��=�
�=�:������"Uq�i��yg��һV xR���ZSr�iXDo4��2�j�
6W�%��1���"��Zݘ*���jg��q�m�Ϊ�.H�:��;���о��Kk����N��<����%���8���~nl�6�(}��%z��?�c7d&�Oa�1�|��	"��L(�ts���Uo*�T@e��m�W��#�c��QR�I-yXuW�4� ؼ���gQ�cg�-E�ƪpz2�!kY''���.�l�֑<��:�*r���6��9@?�� ��v!ۺ�n���KW��ܞ�f�L���%it5�F��PH����`E-$�R�G��l1�;�c���O�Z-z��hJ������xF�2���	�[Ƕ���'f^W0lu�y���A�|i�x�2�H�y��l�0���C��a��ĩ��wm�w.$��ƻ8!�9.e_��E�!ρN�g������l�P��뎗���4��.O���K�\����<�n�0O]�E�T�2{΍w�kL��6�{�.������…v�=g��z��h^�e����yڐ�
�kӈ����^0�:��a��!F��hƫ1��pԓ<Ѕ&������.�U.q��f\�\3s	��M.d���e��9��.�#l�joTU��iG%xPu�kw�-���S��"�T�E����Wf�Z:I�.�I̩���H85;ۙ&���hB������
_��@F��_ʭ��]pw���+@�e�9�U�N�kߢ��"Z��IEY�*U�6�6��j>X�
2T�g���$�H���;#�A]�S���=���kZw
�70	c*c�U�8+Z}��E5Md�u���'���&������E
YKO;._�;0F����Ff���b0��#X}R����x�)�
������$J��M���M��
����(
1���_�������+Y�+y�-m�k>�U�%W�|����{^�0l�U�<���O���kz����'t	��yq�K�Ϭ|�ڼ�����@�;6?�C�w����zR�*Z�DA����"����!+͊�#H� N�\V3B��tD5���ꫳ\Q}f� ljx��d�q1����!|A[p�i�@��o�iy'��'������5�K�a��lObG҈���D�ӝR���p�V%r���e���R�Dw�g9����
��n.tK�L��j}_����2��q�x)o�O^�lN��t�1����wH���S#؎L�X[�x��MK^u�!���n�Qb"[��w�:<R˄.:�+oҐ�;8�V�N������>�>q�p��K`�����X�R|��TZ\�:���e[��V�&�A��UT�~X	��l������X[��M��O8�Y$,����N;8��h��?�=��h�XX���"��7`����w��DIV`7�{�~�D��-Ծ%Y8/
Pp�����i��\�X
���7��@�.��l'	�A�{�r�@)�g�d0��KF��V�x���WPE��/Zx�R|��h��X�D�KvPO�$��o5���Fv�35��-�5]�-�By=�kE_�4��Ѿ/r�d�������ߓU���
�^���s�>����Sb�^�����
c��
�^X m�B��W�}���@-�a;" +��jd�-�n��߽�'ˣ����~�W�͆�����L��6�j<��q�����Z��Z_���������~��ZrK���s\�u\�u\�u\�u\�u\�����4u�҅�[�q��u�҅�[���tyx����uW�:.�:.�:.���]�uOd8��:�wo�]_�]_�]_��q�׷���X|\f�z\v\�������o}�=�1L��ǍaǍaǍa����	dǥbǥbǥbǥb�ǥb������R�_��b�TKǽcǽcǽc��{����d����츚츚츚츚츚L
�v5�=����lX�9n/���^v�A�m=.8;.8;.8�z\p�
/8�'
w�w���w�w�w�w�y��m�@�d����j��)
endstream
endobj

16 0 obj
9207
endobj

18 0 obj
<</Length 19 0 R/Filter/FlateDecode>>
stream
x��}K�$9r�=~E��X�@��̪,� m{����@�^`u��_ړFwϨ�V�4hLM��·���w����������{����-�[+��o�|����ߋ����/���=�_����+W�װH�%}��˟�D���F�o?_�+�|�9�R�ן����}�W����?�/�_���!�7���1�P\���Z������|���.R���.�|��gW\����k���;��ѥ�w�Y�z�YH>�����=T_B��g���Sb�Lސ0c�Ϳ�ϣ�7���l�G�7w�v0�͆���t�e�h4�}rލ���:��(�8:���|���o��3����xJ6;X��Հ��X!��7?��ϭI,��2TZ;%�h,���
�[�k�[�qg�������&r�5i"p��S�^�O�~
?���O/�������^e��^�����2ԕO/~�����B�G�k���o��b��t�?�:������l�~S�H�O�Z�Z�_����+7X�S��s�N�1����8���?E�"��u�	���rW�`#Q	g���5��"�{Ǘ����K�i�:��2�Ɓ�����i��1e�
�_� 4�v���甊iSz��_?����5�����&�юb�y]�9�X?�1e={$�D���S���+3��.���Rx�_?�k&u�"RYX�d���ʵ�z���: �"�,�����������:�
4~H�>�b��_�+��0� j46�������oj<��N������vA�9:�:4��^a���T���	r/Se�{]��H��'�?:������ƒ*���u��+�����Km�-���ږ�i_I��p�H���=6��^�.QdT��O�]S���,��7�.��d�E�N�<g|R)�0R?�`7�.�{v2��4@�Z����xy��ଣi�FU��Q	4�g�>�?�i:Dո�1_���w:�͡�ݨ����#�4�h7C;(�e~�$�_U�X�k�_Q�ߨ�mL�g�z��������n����������n�_����c����c�X�x|�Bb�@ghy|�z���_��O�`2c"ع�o����HFd�Q�}��C��ԌH����F�K���}Ihx��.�%\c��e�ZJ?y/����k���qo�'c���c�Sޗ��84`�٢W?!��xjZ��3;uv3Mp���X��@Ҏ����+t5.#p���d��-R��b��q����zG�)�����X�LF��RR��'V�Ywî㗅%h�R���@x�{�{_�
�D�Y�h��);x�G�s�ÞR���t�NH8�Xi�z$��p��>�C��t�£����݊���q��
,#�v��b�Z�?1sT�!'�c�
��H�e:}vUE��,�?/!�N�i�VFԡ{V�,�`:Ғ��D{��кē]�=�S��3M����w��"��m'.�W��O�<�{�6O}/�c����b8q_�M��h�-Y�)l?J�~�Q���G�dhe3�M�-Q�;z��rD�A]���-��_d�W���-���4
&lM�4�/.�L���5`^U/��"(c���/b�i�;��b�n���S
�=)5&o���ٽ�t:���q��p�Nd��.W�a��w�X��}���owZa��ud���d��!�O�f.�`� 9�FG�n�T��yR@M�����>_L��՚���c!3oD�}���!uWq�䤴81���,� U�Zf��sg�F�n"�q���!gG���0gۏ>P]��dG���xU8�����x#��PO��ns�x�y��x����Ew���=��D�
r�k�Q�ᇊ+���'8��Y��
G�n}�P"L_�)�rk�G����+f��=��<�P|[o?����$��&���7J+�3�q�<�:{���
�<�����u�$�|�<���G��c���:*�(k,	�M����wY5O<WY�G����kx��̺�B1���m
a]�������և1B�izg�>d=��.N?�ɓ?0O�%<Y�y�~�]<�g0�2h|� �C�2b�e�
OF�qq�Pb�̈����!l6C��m��G�);4[�m��7�kkO��)���P�o��j?�~�&���>�1���3	O�C;��i���7a7�9�w�n�,��|DV��g�A
Ȋ���˜ˊ���|��ׁ���ff𞘮���h� ��e�	�4���ܥ�����`}�0y��o�=l(�¶!�����0n��ɸĶ�M��n���W��s8�h��� �!��������'z�˅��ц*��c)����w��d�%��l����'J�b��zq�Ӄ����g3f��(�
��+ʵ��xx�*�l�U����h�������"',A�0�w0�Wy���ۿ{?�(�)о���wtqoQ�����tA��{�m1s�f�=��:�&�y�P����������6;�v4`��(�h/eo��$i/���.gO��<����]0;+"bG�mų���t�o�r��tT{���!G�HdB�{^~ʀ0��c�9-��%�<���榾,{�H=����LG��/��A�*��#u��9&�R���Aw�l���%H�>�t
��c�y�+s�p��\�`X�/�i���K�s��x�������l����Wg��m������6�6���ELP��N��܃��gL9��,�����2�����L�5�
I�W�>��d{���NPy&�CV��*�r<��~Wn�3�p���I�S,1&ɲ/��C	�<��)�}�@�=~]fyƯ���_K��C�{�_kx<��!Vœ��I���Y�ۅe������ͽ��# ����Z�u�l��|����>SA^l"�G%׬��#uu�m��R�.Gp�u��XWO���\�mn�ͪ�(I�fV��p��)�PS�8<|P���T��0�%/�0��1��e7�r�_v2
��}<L�^��*��/5i�jӜ"��	��1�1y�w����0��@g��x݌Wy	?Ni��u�tx||Ⱦ��i���'6}o�8��y�㘅8GQ3����;y'zu���be���m����Uz�h��Me?�F�y��o�b,�d�[Z��
��{��{���h&.p��Şr1�
�Z`��s���� N=�
M��1��q�N��p�(��@3xe���<Լ�&��p���(;�&Q� �Ħ��t����!�?ej=	�i�cb��Y�7#�f�Ta��f�m������h4ִ-T�yWL�#�ktW�s�,0S�ǀ�n�HQ�6G7���0�i�8oR��m>���t�+>M=:�h�P��Dj�'��`��u�㈻��OzBH��Y5G!%
�/a1U���z?dy����f�CY:wz4
i��;�Ȝ��S�aξm�g��e�8�3��+t6k(q��5<!���n������A����†k�H^�������;�(�{�Ⱦ3���(',�nQ���;Nc��L�{Kc��/�M�H/���]5���XX��,�u���;o�O|�6xL,�o�l�I��CO�NJ�=��l���o����x�K���b��L�xF��.��=����s�g?ek{a�����.2�ag�*o�Cu���mj�M��P�z�Z������ÛB6�؆��?�54I�lu�-��N���9��]��þ���D��45ߝ�%���Ӭ-����lp��8{����x<�b:ݤ��m��.�P崎�Eb�B�8Y��~DN
��d0$�e�姿�R�m7|�����x�ՙ��2L.��~-�OY1|a0)Q?�D'��=�[���<3ܰ�6�A\T�N��曀�<�`�;IJ��i+�A���p��+�N� ۭ�8��N����=H��_Kz��8�+ۊ2[l{(8�oS������Iz?u����͸X6������:X����)�8T�p���o���n���%�iZ���h*�xa�p��u׺����I��0b�2*��ir��
���a17^nsx��- ��l��QP	�r�o;x���w�|�f����1��,�`h>��������B�*w�A�a���8`��l��J�b��f�JeO'���L��š�����ܚ*�`�݆W�̐d{8Ev��/����J̢򧽙��H��~����,K��@��sC�
��MO�ܼ"��x��7�k�d��䘫��zЌ�mN���W~�8��D6����0��q���~s+ח���*�9	�݅��[t�M�1������Jބ�$6��X;ۿ�.�!��]DZW�A��{ڈ��)�K������.|����1t����k���=�eN�;m�
��$�R-x�zgW�K���
'�N�Z����ד?�����B��9ݣJn!Щ��gA
H�G�F�+u����㟍��9�y�>Ӣ�I�/��'���O�'�
�������}e�׃x�)f�9�x��&p�9��y�=��� [��
ftl��t"B_���b3*�>q�0�ɪ�s
q7z�kN��nǙ�m6�A���5n����N'}�:�}�nD|$���v�\���l�A˸��N�	�Z���W��{�-/��d_���L�of�6����7�{}��R'�^��I6�$ߔ�_:��$��ϱ�/�3���x����Bt5� �q���?Xy�j�i["����kZ{��)�$-}�W��F>�=}Y�����μ���ޮ���A8�kG-wX>F�#�w��o�n~3�h�1-c7���4L��93��vQh���G($�����{p�Z��j�؀utf���>�v���I�5�F�7T�ڳ	��f,!��&��a�G����4��Rh�q~C��v4\�;W ��/����0
�y���3鼦�73�4O~������K���pH-�(M����-j5+�����/��[x�¼їhɶ����Ɨ ����el�+�6j��/|9D��5F��W���=��0][���I@dI͜���=��L]z�BUC3�W>��2���w �y������.��(ͨ��B�<�c�{��i���Y�C��9T���o����s�`���T��&*3��}��H��=<��]o.��+{(��rk!f�����2�-�&.��nl�!c$�c�(��0J��Z�
�q�T�(���ִ"QE����ˋ�Q��O�Qv�0F�~��
�K2���*�$S7�����w�(��Dͧ*���S��"0�[��_P�7{}�5i�1�;z�'���=�5f\��Q����cOD��N�[��i]BcBV
�,Tbp4�P��x�P��-�<8��2���Y�0LJx��G��k�������x���R�9xG#J�:���͛�+T���Gn$�R�K>�������˞[��B֊J<1_��"t�����I��2��ě~Ѩ�N�u��HL�Q��N'�n��n��{����_[�:Q�cT�Q�卓�
��q{p����2%K%���H�h��X�
�QH�N*"��5,��@2
C@'��XS�M���׹@����BQ�v��/�!21T��W��0�NE���kE@�*N��S���@� j�"���ꣂ���Q�27�����BS���	��m} ؕ����M�����9��(#�Q��.s$��d�R����/?���C��Aw�1Xc��j��	�P�����R��
/ej:'��^u�In�"�<Uݓ���(�|ƒ��v���u,���ȫ�*�i"��)�2�"=t�!�0��P*���ZN|VT����#�/��/ c��٠̡	���c��Tk�H�H�2*����_𪇎ʔ�f��t��ѣPs{�d&%��H?��6u��P;�ZAEE�a􋨪b�!D��Q�	8�*��MЕWݼ���=�K595b̨J��R��u����h�Ɂ����z�P�4ǀ�NM�b�"/w���8P��ń���*��]@�G׿a9�6��h��Y]Uh�
E�Ɵpd^I�W��b;�o�ns��f
��\�7�K\�6��N��m�	�a'U�e�!?u�˜�������O�x�rU��8���@5$bBYD��T#��h^q��UW:�1�i�f'�#.D��핂��	�XR�<�B��HZ"�N��'��d/;�łU�:��:2j��R�V4k�s����e��Ѣ3�+""�P��{̅���L��q<�(�u���Ԩ�@�
k�.�0��'
S����
�0�ΰ�8�`FA�H-������]�cB~��Ƅya��ʝF̀�P�uDw頢zc��,�c]�PU�yTT��1�u:P����M&�(]�L��`��I��Bh}�r[��pR�@���xm��1'��!��N�(g�cG& l�f֊N�:**҉�)W�~�k�ه�I&��(�	j�A74`�R�a{I�ܘXcrY�>�O5�Ԙ�����%�
V��3�`i�h��Ð	I�ץ-HƦ�2ӵ%m��e�VĵjUe�u6�[Wk$����	IdK���	͑�X@�G]�:��U�77X�Ȣ:��&Y�BZ�F��G�����"p��)�"%2~͠�@�0�TD���YeR�s�Y� �d
�����$
9KpA����Yk�*�4�n����R�~ҀH(Q",u�T��U��	��Lu	�(��(Ӗ%�lq��P�K,мMH[uYUV����8���d�rV�$�PؓL�QQ�����j���b`~Ƶ�ED�i=G�7�r��H1`�Tɞ�����iBi�������:^�� 膦�+[#)R�o���'sx�����@EDz'B[�ѱp��S�Lǟp�bJ@Z(�"�T0���LI��T�|�A!b9J��-�Y��݄ay��k׊��ͻ_w�
vPu�J��8K�$�2suo4	
�r0	q!��������)C��(1_�Ȇ߻@�.�/$4-��b�K�):��.!����<�� �QWk��t��N&TD!A3��m������!Т�1"_L��ZRY(�>oW��;,1�S|H�K��>P�p\CW(*_ _����T�-���=G	n(�QY_�z�jxa��p!kR+;�qSQŷ��/����Nq�_i'>_sP+�B�)G�J@Et{.�6Mb�_�n�b����wk����?���DF�/�����{�%�$�/���ʅ(C�ĊQ��-ƪB�?i\��N-N0d��F�Cˋ��Q�xY$+<ES�Z
b?bL�"��
f.��X
.�<'�D�2����S���S ���RA��!d��c�$���#S-��yz��W�R�]��"M����:�J<�8���XrT\Y'(���7���6ow�Y2$��L�ɸ�pR�����u�fmҤ�TP��K�.�^eU��Й�}a�,��E��p�Uÿ`����hTp�RUWI��&.T���?�Bs2kp�p����y4-�I�$KM�@{�B$+5�t������	4��D��X��=�d���Nj7�����iฦ�Fl#��A1��P��v�Qh�H��hp�R�W�$�O�c*5*��Psvۉ){0ʦ��UYT�� ��@9��|�u��H�H]��%��	
�M_�����l�@T���,(1!.�uT�B#D#�eY!A0�BL&���Sb�A�V|�p�"πJ�UQʓ�1����cD5�����[ɢ�銢�hE��@�d�'�N�+�٣�	����&Ug�c4���όʴu���S�����0����ȟWD�h^-2��R��VS�H۪P����6V�XA����4��Rjܾ��$FMesT�<G�-��h+�
M�r�r��\�I�]�N�""*��H%!D|`M�;Z4�0wb]E�H��][HXN�BFخm-{� +�MZF�'�%����p�<��L�r"q�NCg�����)�O��@�e|_c��`�,�r&������H��N�C]��ӠH.�OR��X~��$��@ٌ�>|E̬*��%��X�Erd�DJ@��Y0�^o�-����,6��=;��H�V�`I
�sRV@J���
RBRq��=b�@�*I7�q�N
����F��A5~�+���|��Zvd���a��¥(Gvb)A��
�b�rT�2;��Q����&'j@Y(',��Pk*���Pv�=̢�	���Dp�*�Ѥ�,T�1�E�Vo����K̤��9;�$��e�HZQ�B�U�����d��h&�d�lrxqO
��.1��Q-(��j8t�m���X���7M��$ۋ���̡�֪5�7C M�c=bY��m /+���T��=/m�3`:�ҨЭ!Ԇ���W�s�7�2?�d u�P]pS���GU��FF*j�.�i(WcO�	��*EźD塢c�i�x0��BB��b�d��ZQ��	�X�kv�(�<O�f
�ƒ�X�$ �PQŲ*�F
ւx��R�=����I�R�c�#�A�:.X��0�����ɒ�X#Ǽ��6n%�v�"[M��gJ9�G�
�"����\
�$�?��'��j�1�P��J�(��YU�J��@9�ut�d�p����&�nF�AY��s�Z��
/��bq$e�Bq��I qn���KE�
H�~��V/���r}�'�M��msi�������9��ɊcK�q���J�Fe�T
�ܬVʳ6�$�u*t�j�`�᪂L*b�	�hQZL��R��I�8�������2�4�,y5M61 �ԙ�TD�B@�����J	����7�~�2d�7���eV���<���}�h?� FF��+jN@)�'+!�t8��J:�F T�2Ш���(��@hh��`/���j넑�ɜ�AY�8a�#T� X�9�=��9(�$�Ŭ9��9��x���x�R�aI1M���Ҝ51��<*�ՠ��'T�ՀyyF )J�/�N�ȖɴM�bIW,�K�?�H�Jy c"2�xBDª5yR�V� *)�bLb׼ؐ�:�����+>_-o`1�i�>��P��Q[�6�.���5@�JO\���j�O�h�y�Ry2��l�(�,��}#�*�p��8�
Z��KвO
ܰ$��-b*]N�!"tO����D��e����!œ5(O9ϳ��S�,��4C�Ѷ��|�	�w,�xf|_�V	�,)�%��|�h�z�� Q�>y��"'U��7�ՒQ/f�Z�A+"�b��)I���IO
Krc�Y��hw�OZS�v�����~�E"ٰ�hܴ��y��q'��(�
YF�Q�L���.�}E�S��ѱ���ďU[��\�\2��T!Mb�h��
d�(P�X�.Im,�T\���o4������RE�6��㦜o3SڻP��nj̓z���rn/�b�R9z�W#-��x����G�m�l�!�bW�8���㶳�ݨ �᫾���(�d |�T8��Y,G�vȳB5[p�f��ձc�坃�rn�bg�'3���� yW�ԑU��@6�I��A=4��>�r`�+�6k�n�ah!G1�s'D��۬	�lT5�"D���>Wa����
��"g_`�gt�E�C.����S@[9K�pTP@�Ȧ'n
B�l��\���3W�̴��qE2lgz,s��3�P测�E��G���cb2��ETe%k{��2n�,3�E�"j%��0�7n��9���牭�"AބDa��CB_hDK;�DD�ل��Y}%�:��C
Z&#����"<N�!�Ui���4�,��4�w{�s.3�Ts�@.DWa�M��I �����$P�V  ��E��s͜J$VR�)�DJ���a��UwI!p�j�8Q$-ge��i79K�����H";B�`����
��I�5�d�������n2R��4qI�u}7<��,<����*���z���u	������h��f@sA������U��؆8y��<=��%�O*AaUE��0�`� ne�E���|�E��*̞���l�Q�UnŤ��܂"/���S�g�bh6vӔ��$q�.^�&M��t����Y��rt�.i�Fgp�UjBݘ���ݼ0�U���rQqA�T��h�uXP����9��V� :��W�wNJW�ҩO����,�D9X�wU��W@Y�*L�.aZ���R�yb3J+P������6��	�,_9[qIt��L�����w����1+��`/!Cr�&M5`E����䍲�B�<\��h%��E9`�x8�Z;�٣��
���0L2�{7���
#�-�@���$�5,7-�(İC��a]�Ν*��~���C�S�A+�ڦ?H���=˸�>�\��B��h�ڦO2�ͨK��+41��:�T1�EG���3W؜��+˹(�բ,��Iˀ:�K���Y�Jvt�T	�����N��Y�x-��:UO��|�0Ӧ�DT��&0���kBp*|��&rk�Ԅ��ؕ4`i�`BF�_
�
��I����W=@L�	�5�*�'�k_��rGB/�I��̩�JɲEφ��E�~1�tY�D���j�$I���p�J|�=Ϻ��Xwu����
��*��3�1W4�.!ne�`aE�Z'�g�T½6��Y������
i�|�.��΁AO���ɤ����脣(�4P��jx��l<c�rE۴GA�B�R񷰘�?Q�,`��G��6��K���*���c)5������͇:h��q����s�E߃�e	�b��D/}@mզ���(��B��(k��<)�B��+KgY�Ơ�b�Us��@w,��I��\�E(5�'I�L��2
J�����P35�e1�/P�@"�t��:�i3pR9�)�"˘"頬�YLR�ueU��@������;u�m�,'[�jN���������Ďzj�]�C���)Bl�x���O�rW�$+$i�X���B9�Ȩ�*���3em"O@C����U ����d�����8�x!��5^nN��T�\Š����r�����L`Z[�
�lJP��6�<%�	6F� ��a7��D��P��`�
��e�H&���T�2C���P�p����Hu�a�70�Y��.�Ҥ��
eR�l��+)�sT�+���d%<[c���,Q�AS$�	s7���=�尔=w�NC&�I*��I�"��I�o�#MA�
ˬ��������.D���B��!�}S8OKN%�!�����H�\T1:^H/D��V�(E�$�ĺ�/J�E�	Ƥ#B�*�N�ļ���ZP���:-�AI��K�IXDg"�I�c.	I����
4��L�����WQ~�]�)Zh�yՆ,Z^��B(��|x���A�	�Q˝^ybE�L�	ٝ�c��/��S��=���U�
R]>i� �r_� �ث�\;MB��Ж��mKb��s�zb���e��|�rK�z\�ǿ�K�Fop��ߏ���u�`Z����ߟ�kI�y���~�_��k=��zޯ�[���TO���
��\�+��Wp=��z^���t�j�yK�𼥋+��t=o����t��K������!�����y���"�����A��]_W=�����y���/z�y���{��X��L*��:��u`�<�{^��L˿�u`�h��a�F~���1�yc�yc�#@��T�y���R��bQ*���i�y���R1|�y�����b�XK�{Ǟ��=��[�w��x^M�ϟW�=�&{^M����y5��j2f��j�Gt����&���G����~^pf;}^p����y��/��~��A��h�;Ј}�w�=�@{ށ��M���4PF�p��JA�
endstream
endobj

19 0 obj
11956
endobj

21 0 obj
<</Length 22 0 R/Filter/FlateDecode>>
stream
x��}I�\;��>E����L��+骁�������v���3е��o�� �9\I�*��V=2�����/��������r�zN-����5����������8���;�����>��������0:����?�Mz~n�ç?������_��o'��K<�t���ο����֧>ο��}t��x�O���>��G�_��}��������ӿ,��#��s	��Q��`�������}��~�a������J��H�>�>[鳥�����^���`�����E����n�K�4�����o�������S����0�x�}�
��E���ǧۃv�y}~�Q��^�b�7 �x_���������3--�a��/�!�_��c���'q�"_��A�v�mi�׭�xf��
Ғ2��ޙ�>�e�Ɍ�5�6�:3pF"�X�ûoJ�i@مn��U^X@oϼ&��Ǜÿ��x3�:�������o�H��L$����[‘�0����1�?�F�,�Ҟ$��N$e���1���;
0V��Kv-�����Z��.����A��5�)cO�l��J�5���	��v�+éf��d:�)�%�M	垎�Q�dv7a��<�E��+�3�D��ʕ���X"�퓻�o@�{�OP�

�������:�Ч��pM������;vp�K�_d��q�=�R?�=kD,>��v�kf�W`G��·�9�fL7���>��r���?�.<u~�C�緃���&7��ag�!��B��1�2NjLxꆟ���)��T�0V�_w��.r��Y�1H�2�뺜����y�ZdW,�8��Λ1�U��Y��u?4����?�c�� �w��A%?�-��I�.�F���>+�|v�"��5�u��0A�\4S0d�V��v�����D>��l؈	�$�c9��:� �5���H��ё��m8��d��F1�R�'���B��l#��3��AD\Dž	ـ-�俎� �O��%�oh�s��I�F��Arq/�RnP��kd�.��)�H0܃nH,�V�Qd#��Aҥ0�'�:�v�7�����zu�b�u�tx�d\5C����(�A�\5��!n�>fK���y�b��4��}kH�P���
�]�n/�v`��W6��q��?m�
wؗۆD0�^�!���!B��;*��6T�!��X�N��9`�s���>��TS����j�{��	�d<�R*3n�^����M�b\�!��%�"N�� ����~F�;�!���M��*Y�{���I�w_��C4��W�J%/V�H�S��ّ �Yi�I�5RE@�7�> �%1K�g�R�^�q�7��g�g�4-�����V/>��6o�D����^��yd� �c���A�-�,[�z���N�0��p�c�V�/8KV�f�Ʈ�{�"�if�i�F����G�x�+)�AW��Q�c�TJ�8�?F{>[+�7'l�i9|c�Ŵ;s!������E��_,ل�o#Un�`;&�R�VF1bO{z��
U�'�I.��	;��,���ob�� C��{n��+.�ƍ�ujV��Գ���� ����븭�����V��w^�C�;�*�ej.�6�lF,��Ċ+ۄ\�D�u�EԦ�F�p���;'��8�1�����鯧��a�¿ND{?�>d-$��L�����k̔c<����V��Wx����+v�]^�J�C4�C�����K���	��:��?[i�����a�_�D���?~?ukw�����t:�Ķ�?����Q����.t(f��Bv�i;�Ƙ�d���͊4�s��W���n���v���Z�ro��"؁�	:���C�l�NmGd�
48��b1"vZ
Ƿ-2��i�5���O6"&��`MI8����8&.c�'�I-��̌H�&
�`��":�S�S�4"��Sä������ח����qe�Teũ�\�ymgI������o{6���&��-�gO�2�8Dx�cn�ԁ!޾t�����
YOo����W���O�xhD�����%/���S�0�:�Wcw�:U���.�w�d���[��n�ٗ����B����sN�7nD��-�1����Z,�G�|Q�b�{)3��̙�Ůʉ��.#Kh@���^d$�-�:Q����UH����\��й�O���$�e�B�hl���&��}&�n��'�2ͩ&Q�;1�5%"}HqL�`c��孩^�,~�Z�����C��0t�.'�uWPL�Cg�@���b��q�����~'0Gl�?���[z��,�j<^��\�Ër��+�^�������6�$�+���rM�s����E�/
��d�EZ(�lפ�����ܯ9���K+��D���0aI��XӄI�����n����b�s�ۤd��_-�]�zT
�h��u��������z6�E�Y����5�������FyK�Ԇq�G!���+������ܬ���ZN;Hƺ�6i�ŷuigƴ8͞�_��2q�U�s+5�>�Q���S�`q�f,Y-Ʃ�us@4��Ko½q�<U�ʼn);��gCc�%���6޹o����G�cn`�U�s�6�$6Y���?ެ����Dy9u����5�)W�1�NZي��@o�F�-�Vg�5*�/"FJ��]���HM�/�6��鯸�&޽�'�4��]I_�E̗W�����z��~�jT-��i����U�Ú2�Q�u�Z��jk���ͳ/|آ߭�4~L��dm�%n7��<��w�y���j�|����Y����sݖ<,��2�Q2RȰ�Ş���.��vU���ر�ؿ�:��w~t����]��K���g�s�T����i��o�	�5�t?�K��'�Z4SE#�8?F{��F�ġ쮟ˮ�?�����0[�����/���r�mps�ҚF��qg�~q�
�:r�S]��Pf5Ť�����<�?�	�o����+*?����� ���6�G��I���&�i[��S�L\R}����uQ
���w�+b(�H�}��/]��Ň(��t�d��A��l��H��ș/�]��~[�f����;�v��BA��#�"�J���
��M¶�~�`Xx�P��I���$��Ԡ/�8�o-�ފ�ڮ�?s9��>,u�Fh��̍'l�����8o��tK�9R���p���Ͽ��|�x�s>�����᪎�����^���l|�cK��k��fpl������=����K`wa˾~z 9�~�j$�"���3a���Þϻ5g�:%�F�e9��Y����ۏ��}�/��a|��hJLoڄ�����|�;g]6u�~?3V/��~W�������_�?��2ߤ?�3|ʱ�y��/�~�>+ϼ��g����`w02s�ae�T��~E2�3^0��aEhu�š��7=�XÐ����
w3!&�^2��1�Bz��q�L�ʟ;��A����F����}��f�W��%-(Q�����Q5�$��&��m�8F�u\�� �����#(z���U�F���:t�q�ر�|���u9��4?K��R
�ZU���T�t�#�*����]�rIŋ���ыe��a����܆��
����:l����\u����Mi���T9���$ϕC���}б�y��J�չ��`]|@��Z�M�v����{sB���Q�#���8����D��U�,
^���w��e��ymo�~Ώ~K��ԗ۲��>`JVf���<��k
`U�k/������h�z��L�x ��`C�>D��;�0T�5�N���M�bnDp�(Cy}:�.��6P����-U�m3dׯ�c�ŀ@*�ƓL�Dž������������%������C�5b	�
dncA����r�
f\6q��\Mc��/+�K}A
��n�g/�p��=	t�9+v߻��.r��c�'Yn[��������q{LJr�cѸ�k�=�����R�r�ˬ]Ew�`�ц�鿐KUWC�@$��j:�����>��y�lh ~�řp�qٯS��]�B�32P8h���d7r��}�X>�7���nKN�^7i�SK혽���~4�����돏�V�Z�I��s0�M�[FV���\0�|R=���/2�z�j��7�įtAҼv�$'�lz��l#��ГN5Ax%��w��}a�+��Q�ن4ݹd#����a�j�?�1��+-�;��r� ��B[PV�
-M��u1i��dm>�(L�a�RL�:e�0����r�m�I��K�;���.��X���C~��}Z�D�s4�.�\%��Ep6efw����n�;[�fvM���^���6�gS���K�P<!�%uZhf��Y����at��3L���Vv��$O;��B0����xS[u�P,�8Y5zҹ!�?���2=�ӄcc[ļ#`��;'9g��Eg�0b�xs���ō�΅-�ƽ!�Pv�����w2i |�Q�s<�j&�*nw��4��.�2Lb{�^}d(��� ��DdD�f$	�ۭ�z��`�˸D*(yv3B��(�/ a޿K�۲���/>���c����2��`���q/%���
�}��~{=�ŽY/�� z�cN#$!h�.ӁS1�=?�5�<?qr�P=�=2�-	��Y�kc�6��"'�>_��=?�s��.l�{&gug�<ؖ�lN�]�E��,n�����\�"�GN�C�GrF���uk��k�LJN����]������W���ag�{1�΂�#�M�P�������xp�=1]�ԁ�>*�k�󢺞��	z=g�n��?� {���d*B����("L����
��DW��������n�&ea�iwz��_�ԟ�g�
K�W�bB��������6��M��WXkj�G�t����c�qV"����F�}�2������!�}��:�=�A���K[��=��,���ա����K[��,W��Χ�׾ў]�q�p�WU�+X|��ւQ�NT�3N�E9��b�E�sI��joxt�#m#2�ΠF���-��=���?j◫Uo�ϱ��o�˭�ڧ��ɸ��ه�ǽ�:xD��9������2�y2�	~��F.u?۫e��<z/�|�ĸ�F-�:���}�Tn��N��L5�=sলּv���+%h��#;���R0]0�*��^�?�.��p���'���7���%�#E+��/�zO���%��.�8�⓫%<{`7�A΂? W����/�޼sY'8���͢moM轒���D��@�|&�����-&���jw�����H��NK���%N�A̧N�wnqe{�׽�@F��|`��go�\����7�-�6 �f.ET3��w��#���b�s���Rs|�>��q���(]_�N.�d-K�aò�n��C�_��B�Qۇ���І�;o���Wo����_�)l_���T+ެ�#�_S��}��^y}#��^��?��Lں�.n/���'B��Qf/-��u��<�
Y�o�X�T�	x�{�X���҂��{��d�ó��$�NbGo�#��U�KM؁��:�K�D���R�#R��iʓ>^Z���QN��2������d�e���o�K��d������y�H�>|,2�/����p�1���t������ۼ�>b�C{	<n �9�kH���
A��2�=����w�~���+��I�/BcX���q�G�M�̛�G�%{���[�_ϰ`/L�G�vho<Z}		;
��pɞٌ�:h����H�s��3�����$H�Ms����<b��:
���䁤�:xc.�Y��
���3�v&�3e\��W}����u��@Lj��	����}�6u�'y�3�u���9z�XEgo��(n�W�.A��w����`$tTCI�h���$N7�Q���'��A&�+)I���*��R�P�E�"�BV�qH*/ǁ��P�*�\Tg2(@G:U9B���*���&�<�	::Q��
~�@�����y�6Y+�����*P��
�Ե�^�J<C����'�8�d8�� +vA��L{$���h�R�����_)t�O7*�ӽD�Z�J��/��R�d��R\���m��{.Mm�[��-GB��O�.�<!��Ǡ
)1f��=�#0�=������ڈ�G�}���%��gH�(Xg(��/I�v�6~dVT˻��N�� ��l�O�c��d�
���F��G�s>�iM�R�"�ZFe�А�2�1hLi:��HGa�����3\���$`����lM��@��W�Q|����e	��G��w4�G��4��F��<�vж#s)��!�E�m��+]��5ܧS�꫁!;r2{�u�I�$Y�����8E�EfwgV��b��/�����S�����j�= ����KVS�CQ��+<�W2�`:�I�]z����Y�$uG�'HJ��c�u�L�4'`t
��L�������#8X�K��d]���D5x���'v��F3Pu�P�n�]3��2�����rC1�=u�ldCyřu��QQ�OWkO�דi�p�?�q=��~��I��!��ѣJNW��FPMjӎj�}n3�O�&�aL�#ƞ`G@D*v�(�|�/?>�'�\�ELl�R�Q<6l͛2 ��hû�-��-XFcXB�j��"#g ���#[Df�$�Qފ�1�C�h~�v�U3 DTo݅��]&(hę�v�6+"��BP��w��5G��O'|��l1�$�����J��6�m���w���v��(p�>A��0o��1E������"��퉱#��M[�C��;
҉�)�3�������$��e�M�%�+:0Q�Xq��K�,l1�-v�����L�ռ���yL���\�����P5`H�$�)k3�����t�Q� ��I��W�(3Q�k�e#�5�F"�M��H�D�j���+���8�5����y�B���
f�,Q8��*� *������������3�Q�Eί�t��Ղ� �]0���#+�BJx2i�L	]:\E��%'I.Ȟ�:�kM�@�G�fqʈ#]�/��'M��$!�Z�O�M!P�.K�Dt�I
EEVW�����I�l�J\`��mX@֪	{l�Xu��~h�T��>���I��COr�zGQ@�⻩�DzF���	y�+
�,�{o<�j��0y�Xȟ�����ԩBiЉ��g���H* ��D*k%-R��h��S1o4��X:��PW����
�S�`�it{��І���2��#QG�'u�\60��Ҧ߽��h�?/�'�ڹ��i�L��"�
m�]Tk��ht�7@bh�T�J{�Ԡo�������ï��?>��`�x{�E�Nv��&� �,҆?&���A��$���/�Hp�ԛo�6M!���AHPM�	(dȼ�$wv	�ԱF���v�@n�-Ř�i��l��S~H�,��@��qC	����ryD� 8�-S���&r��ΑBB�nTA�W���a�T/�{�q��UF�Yǿ��T�i�U��g����K)�~JA�0
՞�dM�x�'��Aړ��'�>(hC�
���5uty���=��}����,�����<?����D�'v��l1]:�Q󊼠u�q� +<^�9�^�'����y�1�$Т�s��&�foW0q���ג���;�� �$���0��m�Bm^a����DASȘs�6i�qF���:<��X�+8�d�0�E�0�A|�
$�d>*pD"cf��(��CPe�)n�Q}�v�dɒ@O	'�B�MI.�z��2�:���PE%y�V�����Ʒ;�}I�d)��.��k,�����D�@����B&�T	����5���!��`��ե(�=F#V�,��q�$�h�LV�z�R��ձ$u#XxE��m�H1�7(v���4*�:��͉�S_�.�"�n^1������qiAh_ɮ�`p�P�S�ěWPb

*��PsL�H(�7Ʀ���XT�� H�@
%3�~�5��@�M��%I�	�Uh,�<�l�Dt���,h1!N�vP�B'T#�iI!A0�BL"�����A��
ڸB�g@���(�H�<���1�sTLB�-'1F�lEV����,�B�]r��$
ԕ��0��<��&Ew�Hb4᎙τ
ʴ=�t�C���
*��ݳV`��@��� BFuꑁ��p���ZD:V���q������hƪ	�֦V���E&5����ç��hi�AK�QTi2���=���L"?��zvQQ<Dj�
!�<��i�an$�E���#DlG} !l�:��z��&N+�#������z�<��BZrI�N�`������#N��@�e|^s��`/O�z&�OU�����Q+e���/,ĎdhR(q�L5+�A�9FV�@D�W3�j"F	�8��(�P��mV�pD��Ю������(l��;tT�Pĉ�d����x�΁~U���u����+mJU����jl��k� ��w��.e9�!�t��P������B�C���]o��I�PJ����VS�߇����.������I6O̡CM��B�Xz��&j�QKs��D���D��ТP���#jG��V��ٟ��i�L�?�"��p�d��MrF�Z��ee�-&T�&�
Oٱ�x<o���u�J:(d��X:
�YB3�V�7S U�cL=b[�����(;���t�����1(0�T�V��Ca�����yH̛B�/� 5�P��P�Xë*�x����V�I~����xl�mF�BY�&Yy�hخ:C#uꐂ"�9Y�vT%*V@���'�.�ӿ��r�Ad�����{�o�Y�D�kF�p��]r^�}�$D):1K����R
֤<��w�rՃtIa�R`��x�L�'	aҭ*��;���#HJUة�yԨCp�?�+����1�P��H�(P�YT�*j���@ۓw�u��p����&�F�^E��sqڑ�	'�*�qD|Cq��K yn<�JSG�QHz��^/���J���U��}s���������ȋcO�����K�Fc�T�]�Uʳ5O��e�J�d�ኂL�����AF�h�:RP�I�8���� �̙�y����*��j,�A:��Q!!�(���	%����I4�q�
d(/AA�l�JE�i�X�PE�(N�W���ROB�p�� uW�@(+e`P�Mڵ�VE��Po+��Y�9y��3�I�9��:��q�"G��ED�J�W.")�W	���IkZY$�1�LZL��/FZ�0�Ф�k���I��M��!\�:�����N �$ei�~�!�2R��Rnႅ��c�T��F2D"��'$�zcP'���tQIqs*��ffCqkgv�8���E/���y���cMkvAÅ�/��x���N���<MP�ѓ���,��E�c�#F��C��M��آy!�����4��FU��(Ja��������Gn`Io�XJ��T�ݣ8c%Qo'�5����f
�C��h#�l�����`G�\>�UE��E=>�Y��,��ke �߰��=�G����B�䨆2���Z��$Ykvȁ#�O~�BP�N��T���6��4	�~g�V�|��+i�*���%�
�Q��Ml���YwĬ�i��\� �V�F��_��*O4l'n#�C�1?���:uȐ��ZU~�/����eJ2SG2'����1���a�(��x�Ǻ�����.�6x�Ҡ�	:p�\�K��$����ȊDO�{>�s��f����]ɜ�x���{px�h��	��>����<�'|�tܡ����m�F�j�p�3qǮ��;	��TE�2��P�L�NVf��]�PTa6�сll�(U���SehϹ������V��hFHA����u�6i>;Y�Y餹�Y��xN��9��/0�ӧhbϡ	�]R�ѣ��$a�;(������cAB�IB8���fZ��,�3�yD�1�f���,�
ǣ�,�!2�wMYN:d����|�,lU?�Y�d8���cq���Y�ydo0K�Ό#�g�����prHDd��x��4��T"�a����69����#��Q'$�(M"ɒ��ԭ�V��iJ�eœj��ȅ�*l��)D�2u8���"@�5�
Qy��S$J*9�hC�L�!^3؀��))$�aR�Gʤ��”��&%�A��C["w >���GH�0
�k��+ ��JL�(*P��!U?����7#��"��>M�s�I?�5�E$e��9�>�r�9���]���H��@�`MAJ
ې'O��G��9��$�I�+����F̚�㠤�����An��h2R�Փ���:��JU��t���W䅲�T�NJ��I�JˮZr�� p�$�Dž ��d雺�tޛ =��bG�ꒊft$�j�!4��H���}_�p�B)ʇ�,�k�7]��İ6z@>�	��Vvj &��S�ODzS��hN���ޖ�m���f�+�-~�yg?�A8|�<��h������M݇�m�/����8E��.��.���5ܔ(ӁkVlC��NB�� M�Z��4c���m�B�\U���M��(^�d��OeE�(|�k*$/S�����.\Dj�H{��=�/����U۴
q�P�tY'�s����_����P��l���������i�6��%���dD��O0u���p���5I��ȴ1���;,�1�Ń�/�'$��9�iS�;��'�G���Qۀ:zJ���I�J~t�R	�����N��I�x"}ZH�t���9ya��Љ,�dOL`0�IyBp*r6�&Jk�҄����,`��`AFnr^
�
��I����W#@,�
d�6B�<��NE�!!��ҤH@v��JŲY�
�-�F}�Oy$��g���C��D"MB“*���<��cd��$���7(����gBc�h�SB<.J��†L�N$�OZ��gm���C%%p��2��M��#}�
:v!�Y��:h�C$�J���b����5@��g�"3K.蛶 h��P*�fV�'2�E�@��"k���$̸XH�����˫�M��|>�A�	��3{%4}י��{s�-�U,�<��ģ�h̓�����m�\���m��#�G�>O(���-k�v��Z.y@�Y��h�������$��REANr�[�j�F���,��	:H��+[{;�dn*Eu�=u$YS �4:Q:�r�R����L�3.�s�h

h#V9�4s�-}�h@nA���q�@�_
r{h�Y<E���� ���T)�����+�"F�P΀Trj�*�3�LU�����˪��@#��3q|�x`z�&�7�>�f�^����S�>E0��}+y�^�O�2�ޖ�	,kK�!k��M��u�J��T7��h_D�5���Hv
�P�p ا���B�<�wTJ�G�
�|�}�j��^C`ط��`1j���4�RE��#�H_������K�k�~[c��۬QXA���	k7#��?{��~j;����D�U#�!#�F F�����oTl�m�,z2*FD;݃�Cق�p���^�<fl���T�}f#UrQ�H�dd�,��D���;&P
RI�+e^_�����L�
��+��:�MK$�2��zP���-p@I��,j�,b3�걔��R�Q[E*jwU�>�����1~�C��Z�9���ZN��L(����H�'&�����= ��ŋ̪��:��;����^RN����F0��+dIE"ty�b�d�m���c��ri�	]bE_�i¶:l���Q#�Y�������>��Zw�k�����������8�s���8w��B{�p$w��������_�y�����Z�����k���Z���m�6;�+��Wp=��z^�����y���
����.|�yKw<o�z�҅<o�����K����-]ٮ�E^ϋ��y��]��2<��:�woϻ��w}=����w}�ڻ����u`ґ�ׁ=�����y��:0m�����H������1�yc��ư�����b�KŞ��=/��TL��KŞ����K��.{�[z�;��w�y��?�c ��j2��y5��j���dϫɞW�=�&c��;���[����
�<o/�{����~^pf'}^p����y����g����GP�y��4��h�;Оw�=�@S���ށ��_���K
endstream
endobj

22 0 obj
12395
endobj

47 0 obj
<</Length 48 0 R/Filter/FlateDecode/Length1 3436>>
stream
x��V[o�>ÛZ�$[v0u�Y'q��DR�[JLK�,��Ф,S��k���.�X*ҦE/	�RE���
Ec�>ԏ�>�Z2Z4@[��u(���3å$;��rg��͹�93;�u���^/$
U��G�~	@�V�t��~ĿG.�\+Uo����'�7+UV���1�<��m��^|�]
࿎���HLm�
�|���j�ګ�����U�
�
�|�tV�k���S�.���W���wPV�[��z|e��#b�f������Cy��	^��$ d����o������� <*��2\�a��>�~��[�=�|~ޅ|�A����-�y���K�^*�ci���ƧV���'y�_{:/����6'�NF8Q�oyW�{�tVK*�p�{U�$剌�|��TaV�k�G��|������CJ���5>����<��������(y��WC�M��~ZR�]�S=�K�#�!��$���P�},�P�{|�CFk��N�b(·�Rʶ$0ؚ]O�'����2�.���E�ҋʄ~�j���r!����6��愮4iS���'P�O0!���魓�p�n5�h���,�sK�nU�[np�j�\(�I^kbB)���f��� e"���p��+��	4E��W.��D�S1��E٦�J��ӌ6��#}�O!A��$}�
 [����6�)K8{e4�QF�򉬶�
���8-���#�X�U�,���صܛ�)��dꀁu�#������w#^BX�
�/荎���l���{���=t�4y{��_���q�&�%;�Ȫ��"pN'��s��wr�����z�h���}���9q����m��W�ʛ���Yeŷ�\f˥׿S�%0E>�\�~��X�M����Ŀ�<*����s�K����4�pv�2��͘��Yy�-�����s�����:�}�����ýs�ıJx~B��C;�k�dh� �	^��aܛ޹��
L���1�u��n׏e��^➬G�F����@%�Zu�?�؋�_]�C�����M>qq��C�I|��
�q���b��q��?�؇�?.�é�a�/���$�G��4�0�Q�-gթ��CSfa 8?��&��\2Gg��iRK��i�&�S���L:�/�z0�M�%�Qq$�̞Enal,�߳��+��^�X�*5��&��Tf:I[��>Dg�z��TwV����
i�}��x���z��嘫A�=�]e4��tӹjטm��2�J�/"��m�x�j��+��6l��*eF�\W�i�̩�
��l�`���ڪ�R�Y���٬(T�x<vV��Y��he䗥E�Zcf��'�-u�e�,[!��<:���0�ׯ2Ӿ����Dt(*K��îb<���%:���j�̭V��J����#�г����h| �{pO�'� �C�aD9h���8f���]U�)�8M� ��$$!�7��i��YD��'�!J!#��81�(>f
�`&�͂K���5#=��=�z�<s`�,����ř�QVd$�I�T��ڍ��\����K.Ӓݯq��!Y%��ѻ.k3){cU�Z:�fb���؋Вc��xQ���?QW ���9w�����ҡ$�9���&��(�ؚ(	T�]N��F��/#�@��E�Z������dM)1�K�.%�v����Őq'vTQ���,W��07�>ob��Lk�ٲm/f���ȷ$k�Ψ���/�X�59��U�"����_�Ҷ&[}7��n�(�O�ܰ�7�\
�]�rG�-'PoH�k�����RsFֵ$�A���D&9�Y�[8第�x�t��AqϺ��ʎ�J��aK����;���wЇ�M��MN^�4��h넼�_�_��?���^����<���1��
endstream
endobj

48 0 obj
1939
endobj

49 0 obj
<</Type/FontDescriptor/FontName/GAAAAA+OpenSymbol
/Flags 4
/FontBBox[-179 -312 1082 926]/ItalicAngle 0
/Ascent 0
/Descent 0
/CapHeight 926
/StemV 80
/FontFile2 47 0 R
>>
endobj

50 0 obj
<</Length 230/Filter/FlateDecode>>
stream
x�]�Mn� ������ba�M���HY�GM{N��r�"��a����O~��ly��}�Y�R�f�|p�k��"�8� 
��|S���IB2;�kƥSl[!߸�f�����wB��C�a���i`=l)}�!�]'��dҳYPV��;n���3��	AW�\���pM�"�0�h�꠽\:�����+1N��;��T��ךk�����Q&���݈8U�C�S�����J1��o,�o�
endstream
endobj

51 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/GAAAAA+OpenSymbol
/FirstChar 0
/LastChar 2
/Widths[365 411 355 ]
/FontDescriptor 49 0 R
/ToUnicode 50 0 R
>>
endobj

52 0 obj
<</Length 53 0 R/Filter/FlateDecode/Length1 1117/Length2 6567/Length3 532>>
stream
x��eT[�qJp+Z��nA��[)��RܥHqJq�bE�C)R��J��.�]Zn����q�=���we��<s�w��}׏� wv��v��y��|�@
;'K7g7wG;+ 2�'��P;+w�%�����2 2���[��+��_��4,�`@��(��}=g;W��Ṗ����Y�#케&|��������)f�;;z?d��ý��<`AA �� B~�����\gk8�����z��� H����oW��ݕ�U��Nv���G�0g�@��Vp���
�_Hh�@Xx������v�P��ee�:�ݑK�.��@k8�.r�@��a����;�=�d�Av����#���
�O@zQ ������r~ ���!E\i��@H�B�X?R�@H�!U�b��7���!]���@H�B�x=�пf�����oCEJi<R�
�h�)f�0\~������\LJI
 ]`;�CKHQ�B�j>��_����0T���X ܬ���Vi��@m��COH]k���P��>0��>
 }a�Ѱ �T񁐒:����M�q��<ȹ���0!�����9�fH���c�4��*d"jB��_oS��2%�̯it��ʽ%����ӝ�pb�R�]��-�䰤�>]�͘��Y�mV��T��a�I�=��y8?W��sL�����C#NnJu@�1���x*g�EL�Z]2�8ز�R+�}�*�ǯ����f�vf�+���L����U/9��\��
�U�w�Ϛ�8����1�+R)ZS�`ɪ������7!d�̠H�EO���ht������S=�
7�L�Iie��)�u�CW�E�:�=B�F����p�7�A�|ƫ�>���������[�j�
Aacl�۟_�1��x�B2�,[';��,��OC���k�H����({����Z�o;6��A@��E_ .�wh�j�dz�O��8��>?�{��V���ONj_P��IN_'ϑ��ߚ�N����|�]���S��Z�s�"�7�C�����\E"�U��� ��+�t����^m‘]��@�TYj����/�iK�0��OD!A&b|L�de�/u�w���4a.�3�n$��b��1i��H�ðawFs�<̂g[R{{�qmW+��㱿�7��.�rK�X}��,�`�2Op|������*:�*ˋ��6S֛U�4�u��3A����1�t��.E�4x/,���ށN��w�y\����l$I�c�:2�߾̛��ŹlO�^�1A2�)XK�Vn�[����\��
O���F�i����3�Q�b�99�}�6�(R|�D�܃
P��ݯ��
'�[�Re������G��{�{y<���<�~�T��䑙��+���ϔ_������~3-����+�r��<�
�3ڂ0j
2�mKU�8�_���q�k���t/�������tz��@�.���N�/�V��o'Ě'q&6��JzB�
�p�lξ
�#I|�%�K��A?6���p�-�?b�&�U���&�~��B)o;	%��XDC(���{MwG-��R����T1��ʭ�|~2����|���e�a#?�	~���-�DLƍJ	�\VP������V�z�dl��	oJ�E?�0c��%G�:�$�#]�|��y����<0�7?��-��p؛��J�{X�`;M�Ea�+~x�B8�Ǯ�7W����X��q�L�
�2�����8�xڎ�]$b�ĵd�G2������l�($��/�(��&��+�H�58�'��������޸]���k�������[.&9f�}xDq��4��ֲRy���$�	�#�N��j����,��sN�`L��o��}h�rg���ǒ�'�\rLf%+�Ґ3��jT%�ޥ�>��ֻ�Ppd��[�?�rB;}���L[%�o\@&���l5�,:v�����`&5s��+������"_�p��R7jF�g��[�!]�/Jї~�wf�3%3��H�]&��m*&O���]-ũ�X�л�u
Mհ���_�b���,�y��#TT�3���!��/
��'i�Wp�� ��k4ÝE�9'f�~�o#�XD<O'��W
�\ۍ�YY��������O�Y�R���7�<����ד��_�P�7��%e��駱�g�#�뚐�ة��>��1-+����E�ę�EjO]��Cml2�ʆ�R�,�ǙT(�#
���޼�����(�./LM�$0p����U��y��R4��l�X�UɜjH:�Z0��MW�q�D9�
y�9��&��Ts�
;�p��L�s�x�J�Ļ�_7�g���ðb~��Rp���	����?��̈́FR8����@�_v9��ׂ
0�I7��?�
�c�``Gw���1:p�XS�_�c��,-��E�����C��^P1��YT;j����]s.N�m���r4��	�ë́ձ���p�>^�u��U�e�qWK�e�p�N�}���Zn�C���`q:\M��Gj��(���3��\P�Bף���Z������+��dR�j9/[�UDHxo��<���.�:���@�����r�M.�1�&�4x��h�d
n™g�?J�x�����r�Ƨ�l`��6���*�+(4�}��lz�����tlj6��aqcv1�)I��%xfh�xE�-`W�1��%���J��uC�}N��G{$ݾ#Б�Ti�[�ڥ
����a��72[VFU&��Tz��Z�v�̡�q�C�ؖ\.G��r�e���D
��+�b~Ӳ\�VQ�3N������η�ǃ��ֳꀒ4=�8�:d�ӄG��~ɻ�b�m�t;��M]`�(轵ć���?�>g!T�jU�A,�$}��}�<qڜ���"��o
x��Տٟ�)e���=)��5;M�>����H��tG�����I�fq�e�F��5�}��Ҙ��]���5�l�M_U���z���)C#����tr��.���^˹q@C<V����� ��7AP�@��T��i���kf���B�R~���C�:�j��� C:�\Õ(��
�N|��*//�O�u!æ�U�gBL?e4Ե�c���EŴ�����C��
y��:�=����w�H���~'R��2�p�;��F{��"�<�)/�/I½�{�g�Y~I��(`��ݯ8o3��vā��9b��0��p��q�2�0��8;��o3	͢��f��'1�Fգ���tWr�]�w/;6�s� �=�I)W��LMo#���2.9W�}���8�??v�*�V�ΉbT���LEn�n�H{�'����FT4�s��޹�Pɦx�Ui���?���l�������@�
��(��OJs
�f<�;Yˠ��F�v�����m�y&q�Z���L�@6��&����U�gء�5�Q	u{ﰉQ���%ZI�Z^~ۧ�Gx��dqL�{�X�`�:��>K��M͏sխd�d����v1V��B�j��L����I��|U�T1&�������Ŧ�[_��N�N����ے.A���;��݊�Cq�-4Z������px�u��b�U�� ����x��ٛ�������Ox�J�4T�¨J�~�L������;mY7�.�x/�[B�t��!B���2@��F���lP��#dKࣁy���
?�woA���ھ��u0��.���ËM��x�G�͒�xJ�Y6�Y-F�B8�����t��b3�u�N'ԙ}+!�*:��1�CߛOK����h��7[�#-&���ˡ&ϧit_�Q½t�ϊ2c���D���b��J�7�ɝ��x���u���e`���!�"q�.�~��Q�Dӛ O�7=��1�@�6�S%W��}1�0:2�E}�tOU��6���~~�c�DV(f����]�|td�=�J
���1�{�]y�H�4���)Cm�+Qs-�4��>�J�Nس��ٴc�ߺ:�it��whe�9���[�2#Tq;�.�!�rU.͏q�A?{�쐅�;[��,�v�����"���Y���j�ȗ��#3���rS���S\�p��'7�"ס�Y�o�,;���	ؙ�ѕ�WR��N��в�O����b%R��?�hC�L<��"5#�
�=u��ȫBm/J�Mr?ᨵ��e��T'�_�}ړ$�>�yW}���3��*!��X�x�CH�;{@ȽM�{����IKd��i3�AO�r���9�A!LNx�Xi��F�[���E��s��O-�ݙi�b��BT�ٚ&}���jG�ܜ)�8���^��E�oh�Hn��1�1��,L�y�Dz%����-X\�E�R8�[�y�����x�N�H�F��I�X���5�
J5�%�T۠�ҷ])�x��#��<��f"�$��^7�[#)�+$pt��D��x\Q�hl%�c��Ȅ0��)������[�)�ݡ#��8���z�
[�Y��z�N�EZܢ>]�
���[�p�,v���b)q/61x����;<��ߨ�����_�7��j�4`�.��en��A^��P�S��ɧ��}�r��lĸ:}V�����O�B3�Z���#�d(_gᬢ�F��I��
ף�MTb�{|آ��?�Vk��A'}w{��<Gݐ��A�i�hj�ݷ����a|/�֥�Xf��b)�҇��7�!n�}��R��3{����D�U�S+�Zl��y�i�/ }�c^���v�,��s��U����^D�k��SE��F��F{�8�շ"�Rt$su9�g*%e/v,�y*�R�7I-F��4����d9t��fF7�|�;M�(����հ,BϋN�
��>F�w�����(�s$񤝴w�zM�VG��7�@�+��sy)_�p��
2���W3.�]4�t+�!���g-��!�+��?��c��Y&%�v
�ݽ���Y\g�N~bNT����5�*�V@f�t}��Y��#Zcăj\e�rT�����5���Yu|E%���8��Zc��q�����ٳ����_�*{g���s�z����9�h$U3�����r5}fͺ$[�,�֤��mD���X��ϫ�q�uO�v�Q�p^¤�s&���s����(2�,�&��{��
<O(���&Wf+�\�+ӌ���'DaܷXcp��^�=%7���q��#�xȯj\�������'#�O���5O�s��"c�g4x����9���ߘ��v���lJ���x#gGs;k��*d$[��֎��Oo�@��z�z�9��9�>-�Q�m&�x�W$Q���M�&Q�X���r�vBe�?[�t��p����}&�_����)�7rhR2ڜ�+$^��i���0���0�/|�M��|޵�?��d�}MbU���;/,�5���f%��l�~Ǐ���s#ە�g,��z����H�ޣ�K�
gX�T��<�-��~.���>;�� R�E&*	j�������QL�ӗ� H�	�U0���#E�\t��BY�)��V�^��W����Npz,F�-��Q��#�+8��0#��l	Ý�T�M�T���b�'
8�4�a;�Y�:&[]�N3�,H1��	��m��m�3z����1
�V�D���:��B'���.�Q���2v�akp—��.���w�V��+���$��je�z��[fXM2Q��?A���6Q�ܩ�}\>���u����:�J��D��LlU�$���/�x�Re�j�p�>��;٬t&�b��sg�m��~�x��\��X���ٙ.f=�.�Z�y�n��-L��vFH�W�#N�b�ֳ������U�G%=c�w�-c3��U��:���n߄YY4u��`X��W�	=c��x�L�m]�g��=MY��z:]��S�Tsx�꽟���
"Ӗ�ob�aoc�H�;��X�m������Vt�ӗ0ARͥ���܁u��ƠoO�j]�A�@�6gqz(R�M������|���S���V��C�j&�������Z�\��:��o�Wf�1ޙH�o�Y*���(y]J���48S�"_���@l����Ur�Q*�9�M���R,*�ʎ����~S����:�){�Xi�^D�w!�_M�|Fc(��^
��̝�j��B�U7��
.\ݗQ�;)j��&�z�z���3�`҂�ms�
4�z�i
�@p#�P�$��,a�^�ۗ��U�KՓ��bx|8��zZ~��R��$����B�07Kt���1�xzm���3ć�ԃek"��(�3���d����8��:0P@�;N��r�+je��#乼�f���<�0�,����T���㛶�B;��G�O�>���h�#�!OՕ����U=����� ��^h:LQ�/Wr�����t�l�X�U��X�d���뿂��m�[*sjϝ��U>�'���06g�{�,՞f�)�����~��5�tC1��#[H�^����rf���R�^qdqF� d��C`��a���E���y��ڏ^#ab�W�eTWNF��?�è�X�Fr6@�Ce��n����~$~UPuI��;~8UBz���F�( :���iY1lj�k!bӫ7p�� b^�QɭO�����iUO����l+��;j�"�5RmJ��N	^�U'ݡ�s=�5b@��o+N��ި�c�v��Ų��^�Gז��%���Ɋr��RF���ʡL�(�m������8L�ԟ�{�L�|0:��;pg��)S����{U�m%����3�H�^1�D��W쬻��'�QB�>��D�6F��
W˶�9�Q꩝l{�gݯ�s���X�7� -�i�s�6_7OH�BB�*�W���/�sGs�aX'��y3�#��u��y7/�[�Ү�a�DQX��<�1����h�#=�(�N�"��7W*�����:��W�]�պ�mgt{dN���.�o��rbz�\��U�F�0�=B��V�����}�z���剏|��vl�յ��nh��W"�u�7kMb�#6x���F&E.�)�2&�W���ӧy��Q��<�3xE_��e�+��f�G�vJ�_�I$SG�D�ڸ��9/�ʡ�y�
�є�_��ޓI�m3����T�.4V��N��$J��l7̊�:�ɣIqd:yN���ޤ囓8�;��
��J�!m��3!��&LY�H��g4�����5C��_���Ni;����$���d*�����S�e-M��������������#��w�@8�/�k�
endstream
endobj

53 0 obj
7241
endobj

54 0 obj
<</Type/FontDescriptor/FontName/EAAAAA+NimbusSansItalic
/Flags 68
/FontBBox[-144 -284 1154 1071]/ItalicAngle -30
/Ascent 0
/Descent 0
/CapHeight 1070
/StemV 80
/FontFile 52 0 R
>>
endobj

55 0 obj
<</Length 416/Filter/FlateDecode>>
stream
x�]�Ao�0���
��
� �JRJ)��V�� �E��C�}=�+���~Ϟ1C��{7������4���u��N�QσK��~��e�ݥ��4���Y/{w��$�֮����M?�[�������ï�Ƈ�4�ы��dI]�^Oa��v��^4�]��>,��1��+��Oj$�-�tc�ש�Է��:�j����D]��Z!l9��߭�6�f�<Ձ%rU���e�/���krp��\�f~"ǚg��!��_��pϸϖ�
��,��l3�c�R	͖���S���-���e���~K��[�x��_@���|nm�Yz�x=H졇
5B�E�oB�8O<=��!�g��w'��C��C?B+|Y<�1K
��+~��y��3��
N���8�+>����c
endstream
endobj

56 0 obj
<</Type/Font/Subtype/Type1/BaseFont/EAAAAA+NimbusSansItalic
/FirstChar 0
/LastChar 42
/Widths[278 333 278 556 222 500 278 556 500 556 556 556 556 222 556 278
333 556 500 556 722 833 556 556 500 333 722 278 500 191 278 500
778 278 556 500 556 556 556 556 667 667 722 ]
/FontDescriptor 54 0 R
/ToUnicode 55 0 R
>>
endobj

57 0 obj
<</Length 58 0 R/Filter/FlateDecode/Length1 715/Length2 2942/Length3 532>>
stream
x��Qy8���6���k���f�%d͒��,�1343c��؉��[%*K�׾'�Hْ��J��^�w��=���q|�}�w?���y]����u�1�a�d<
�U���Ѿ�${8���AZ�4�@�k5.(@�D���r����4ʋ|�����E��`
�E��h�g�#�GBY��P����RZ��t �
��7t�r����F@��8,������@��5�6�jkP��Z���z��_� I�����$�ϼ
�)�"�/��v�/C�PX�	�,�Dc���&'�d.��2a@0@c��@���U�8���������Gl(��	(,�E���'	���@
c~u��	4�/�&F�Z��(��ɜ���@{�P������?B�B�i��~�/������{���_���+��_$��d���{�1(�
D!�R�rvk�uE՛dʯ�3
b��.�k����+�����0(��8������^��.V�_���L�ގ�ݮ5���T�;v$Cb	q����JΠe~�[�g$�$�~�طÊc��sC�d[>��s�I�"=<���~�.�R��������GP/�LM;,[%�~άJ�!~1�#��,VJ�?Q�����Ӗ���������z�.-m�sJ���(�sM���2���R�/ٸM��p�ݡ������8�����S|wo՝���qs��m�=����V!b�Xn����/6�wHw�N��W�nR��-��O}�,�Ufw�j+��⊒
d%w��h*+A-8�|H�{@C��c�ƫ,X(k�H�׍j�g�J�$�(G��|�P���6	���`:�c��V��+.�����|}w��yK���z7��7��j�#[�a����.Py=Lb�iF��D��mʉLZƓ�y�D���D+
��\53��6f$�Iԣ8�y�<ۡ
U��ҭ���u��U��(g ;���Q��|�-�� ��X��D'�p��FE]M<%E��C�ù�͵����A�"$
g�^��q�q��y�d��ʧ���
��\j&9&��:���͎Oȫc�T8JM]�Z�jj톶?Rv{~`���;V��[�W^5�=f��Nܒ��{�\Ѭ��S�L��2�	��\��O�J��O�����ښ~�ΌO�	��V�+:��Һ�>��M�\5[Y�S,�����	d�K�b&'��_��s��6�rw�dW�{��2�Ӯ�4-B[���I�\��#�U�ج1Ś|�\�����,A����:s�r�7���z�R���;m�v���/����w�}��JOf��N}r�5�Z�m�0v��Az({�����Z7�����v����N�G#�Sl'5��(F������my��e��e
R5>T�Tۺ�YZl�;#�����|����U_~�6$Q�?z ���tZ]6�`�YL4�֐�3��f�˿��3��«Gm�+'s��ȡ-e+�X=|�|䀎>�b�Wv���E9����f���bL���{��L�x��q�ȅ���bu����[�&޳�RS�����Q��`V%G��ڠ[њZ�ȑ7�]�e΁]q��e�*�u����1����Y9����a��>:�z�˓�|Q��t�a�n�����t��Ƿ�T����8ʺ���	$0s��V�B4d:;D�������&뾵͋q<�����9�YkJ�z��r�>�e��{��BK�#���N���Z�%�E=�Q$�������W^\םrr��h�WτŰFM^H�n��Xq�~���ԑ��;��=�"��X����͕ܶͺ��$#�,�0cҖ�ο>���m(�@q��_Y�†��A�}��'�r�d�u\�_�#���';1�}��c�[z����:U�4qy��=���q^�#�E��}���gَ�H0��]#ۇ4�/�u��ۣ��[�dO^��pb��s
�c�F �^S����M���eV-w���ѡ��y��&
ge�����]^�����!��GjĻ�-���0&�)`�(g#�UjYl�&��b��%�����L�+^��4�5.��F�o;�˙>�v���Q��.ߗ4��87�y�}ײP���Oz����9��ʖЭS������/�Ĉ`Ax�M�{z��h?�{<7\i���.�����E��ϝ�<֦�G�~��VH���">\�)�m�gW����o��;�=��8����+ncY��@�D*|��|A�`h|��T��3�EϳN7^7���5���˽7�pb^BE:i�}�\8)��\!˺]>2ɘ�Qi�QJ��/�r.�I�i:+�!�������\	jm�?����%�ε.��%�ʒ�w/�����c��d��9K/�g�HS�c�O|�}�L],����d�r_�^*ѷ6�pA*,���6��B�D+�l�v�NĘ0�>��npu���ZВ �Cʄb}O�͈�'v�\Ԛ,p�\��¢1�L�6�R49��M�5�x�cn�d>Z!�e.fxt�I]��Y�כ:������Ԡ�"�?��r�MP�/cfӛ����}��G_R��4�3I�ڰ���<J�mm�|��o���2��+���u��}q���d
�L��z����t���w9�o�����Y��,�j�G)�,�����ɿ����I'/�>�b�3�HJn�Ud'ʹ�^75�]�0W���eӗߋ�����9)%����c3�KT^�|��OF#���cN�{@F�:l,fL�Z��×���e1����&��ܹ%3k�}W�q��;��g�u��<��{���z�:���(�m	gT�8b��a�0�Y�0x���;��t!Y�96`=�21r�C�P~���H�Mq�N�������+u��+�l� T�I��J�pa�u��T�-+�˻9㸂\����Q)����,�䧈���jJ���Zb忞;�=m���!T�@�EX*���+�� 
t�ݕ��G����϶?Ϫ�
�����
nQ�q�:�7Ȉ�M���	�ĝ�\J-t��o�����0fwpEGˇ����%f��k6��T���!���~����l&G�b����Gv]\(��uyÐ��o*n}~h�ӸyM�ު^��A����o_g0F�;}'��Ǎ���ہ&gKGa7�l����S�HSw���$����?�г?��V�\�[�J����W� ��ټ}v:D�{�l-G��x������ڼ�3T!���iV
<�Ux�m���,H�z�F���/<�I�Ұ"]b���U�t�r��&z�E5�{a*�+�_*-ޓ�kJ?����o��|��R�8N"�Ԭ<E}�k�!��.UKӄR�5X�)%T�ZNݴ�P�)�\�?��_e =����"Άˡ��פ�h�6�+��rk=�p��%��6�ù\������
N �|�������
endstream
endobj

58 0 obj
3439
endobj

59 0 obj
<</Type/FontDescriptor/FontName/DAAAAA+NimbusSansBoldItalic
/Flags 68
/FontBBox[-144 -309 1196 1074]/ItalicAngle -30
/Ascent 0
/Descent 0
/CapHeight 1073
/StemV 80
/FontFile 57 0 R
>>
endobj

60 0 obj
<</Length 290/Filter/FlateDecode>>
stream
x�]��n� E�|�t���%�R�Ē}�N?����Tc���_�I[����\����Z���N��{���y�[��Ai��\*�U���yo���Z�S�����fg�:ɩ�'�Z	V遯>����ݘ/A;���z?�5/�Qp�k���-ko��<
uBW��ٴl�`y<������zɎ,]/>[륉��qz,<����D�gȻ��-��w��sE>�&E�Hs@>�&F>�&pI��B�A���+�f�Q����0��ظ�[�#��”���4�AWX��Ɏz
endstream
endobj

61 0 obj
<</Type/Font/Subtype/Type1/BaseFont/DAAAAA+NimbusSansBoldItalic
/FirstChar 0
/LastChar 15
/Widths[278 333 611 278 278 333 556 278 389 611 278 611 556 556 556 333
]
/FontDescriptor 59 0 R
/ToUnicode 60 0 R
>>
endobj

62 0 obj
<</Length 63 0 R/Filter/FlateDecode/Length1 1849/Length2 10972/Length3 532>>
stream
x��UT\�֨�w������ݝ�B��@���	������Sk�/ֺ��>ܷ�NUk���5Ƙ���Q��\���S��Պ������l�d��a��`eGX9���v�s+;gD�'�a+kD�����X�w��fNV�?��/Z�vn^Vr�N6V���m������/��|E6�B����[�Y�8;���w��3�������l�������X9gk���K/���P����?�to���2s�s���f�l��P����������
0sw7�Cd�������s���X�Z��,�.��)W/����;�_�l��_��;��7p��'h�7p��7h�7���fo^��o���p>�^o��x#����M���b�F`�7������ͅ
,�������B�V�v.�o[Y�y�Mb�I�X���b�os�r����?V+Z�X��+���[9;ZY���,��F`K'��p�%��l��F`C�7������ll�.�V�{#����]�,(�F`1�7�9�UX���R�o�2�����jk�v�����
�F6�2��z+N��������e���`3�r�I��L��fRo6Sx#���q��
�.o��~z8�y���J���zk!.��$��l��F`+�7[�;��Ks�ռ����a���V\��-:Ks��7����|n��9�@��G��F������l��F`k�7[�XX����vo���yX9��;�<`5O���{��������͜篤�x��	/X�����GX����_�������r��������of��=^���?����p��{;������[9����:�-���
���?
������g�����bb�BU���U��7��0��܇�̅���eX�?��G�υKp���j"�T��P��90SI�ngX2T��%'�Z=�ź׺�H�X���>�e3���KK�I�i���gO��V�b}��=%&EZ(^��'�r�����YUH�����W.��V	�u���CA��S޻ѕ�JD�޼�Gi����KR�Y�z��6�L�0��_~bZ���m{�(��ҭ(�#�w�|�A
;Ŏ_Ѣ�s~����L�O�8�A+��߲�>��{�*@�	U/諺TV�'=�����nho���p��w���5*�%E�������{���P���R�;V�#��q�����3�ADv�+1=\Z�p���*�򢢄��ZL�$�U�:x�K�92��k����ג���f͎�?�ލ�Ю��~���aO��#�ݔ����o��j��e�ʠ#uυ͍�v՟�<�-�9��sTyƖ���?�P�p
'jN&�u�'�[kS��-䬦�{T��
���
d=E{�P��c�\���(q�b�xE�DmP\����ߜ��Q�//���U���<k;q�i��|��z�A��#<��=��L_�KV�@��s��5,�/��0��4�����|�4@b���+�{�y#�1��?/�IV��h���Q�=+m'���߭�檀�*
���r���"~"7GWMi��M7��p31E<6�_g��`�}+��Ԇ���-.�h�2k�e�?��GK�-�L?�c=�[0l$��B�z='\t���`��Y���(��|D�[�0P~�w�m+�a�,Z�]g�2�y���1�mv��#U��a�5#�J��G�����WՑ���`%hD`j;�L��-X\|�U��^��_�p�БS6��^�R`�k�z��������C��C�ޭE�2�fGK/��3n�z�(<�zÖ�t2�~)v��u4��$���	��|�uj��9�D0jwS�Gj���+DѴ�Q
��O�
�Pz���}dGSY���;��醿g=��k`u�G:�B�S���~J����n� �QI#�YS{�u����r
���O�#5�~s
� �"�u�����n�m��R�V"?M�BX=G��~�C���X?����#���������#����s�'U����??�U���������f��'F�.A�
�1����{�37+��_+hե?��lcm�i|��IuzB��ʲR�N��֎�A+~����b�D���G��L�ԓ���5�-����R�w���������ǟ��r�2���,�"�΋F�ݍ~�9f���j�#Wq����kb�I��v����E���3[����X��:܏~���
X^̋
��ˁ�[�'����sj����R��i	�9�@��C*���i�~�+�J���������l��CV�l��Q",O@���?g�m���m�1my�U��5N�al�
2Ʊ,�~#��jt��G�-Íy���W�A|J�Mlo����V�o&�*��s[�������W���9B�O(���ͥ,ؓ��1b2�􍔘��jFfL�7������I�D���\�pE���������!16�u�tS��7�ĦA��o�N���Ob��ڵx\��f��7�vMNo��1G�gT�)dw�@�u�Yj�0��v6:G�!�)����a	6k�9�P!iuXQ8a�Ew��<�2��a�V̓�g׎~>�K��̆;9ݜ2e�n�$)g�c�I�����^��s:���'���H(g����ޏ�s]��hF��":�&��K�H5+�\�aq	�E��C�W�?�	�c,@������8<��uڣ�<@4���v�\����+Ռ�#TS�����
�3�r
!f�&IG��wGp�~Q�=��3�)gߏQ�����_���H���֤ܿ���Wj?��(��ýR[d~��[t�ab�+c���-nYH�n�s{})%���{"��~��Q^"��/^$�r��	r�Ġ��DX;?ӵ�v���»~T9{%1[~%��v�Q�.�S�*<>gK2J�`�'?; ����a
�A���1��U(��F1^�	��M8�0HQpR�����1�\a!ak5������Q/CnGpt4�um�8^�����^Ԇț�Kg9�D�ѧD��Ρ����U�}��s|HӔ�����`Fv�;$q�N\J�Z�de'��ɸ��"ɯ�pcv�'

��'�3��z7�VjIJ٧nPV�K�@\ą�sb��P�sD���?*[�)�������AD�*.
����My�t�6C@�x
X�=�Ǘ'���*�Kd'<TW��7�ͦΖ��
��]��Fe*�����,�G����gy��T�1y�n����b�1����Ɵ��T�h�{�ȏ�eޑˊ.T*;�0�SP�cb�{^
8
eP��14�Q�I����"ܬɺE����4��z���w��e}+�-���?��r�z,�G&I����´�i�P�+�Ԝ����F
uxe�.'��؂'������!�LJ��ĉ�&O�;��ܔC�Z�h!5��82l�����Z��E�ԀJĭ?;�.��q��o5,橓������2B���^%��1���ڈ������FP�y�
�Zaf�����lOM�5�k��EPEZWز�u���;군��8r5:�nk�����@����ߨ��7��p���"���TƟx븚�>:D�δ�Y�.�v��͊�Xr�O��#�f�մ���cF�P,�lƑ_��ʣfZ4�3+�|݈�_�>���"׽�
[��p�:�m���Ԙ�Z�;g0���C2�C���}!b:�������h,��,�S�)Ǻv�>�n���FuM��d���:[��(���z��_�|�^�n���g`��W�Ǡo��#��xZg��Si!��g�*�3���‘KpDA�����i�_r�6Mw��N����sb(�ʕ��y���dC�������Ji�f�H�m==\}�>��1�:Ԉ]���Q6�Ya��Rr�E@�Ĵ�הD�_����Vމ�?��*x����?�E���e���8{��U�D����� ����먳qR�7�-T����!�~7�dG�+��N�j} ��
���F�Ͻh����K�*z�?������w	��c3��}����Q.'j1
���^Zj�������"���)�X�5r�����gmN':b(�����k�T�Zz�q��В�2�4���E��w�k<y[J�{��'X�?M���h��Z��|<0��*�/�^�|=��([�L��K������}@l�R;Иoi����<c����Q��OI&�1|���/�+�w�Hv�<І۝45���T�O��(��LV�t��'��(q���`ӄdnŒ�#��-���H�C�k�vԷ����O�ާ̐<̮�K'gW%�-�M(Cڶ��ܭ����yE��u��?�_���k�z*�3q�΢�(��̎>� y~�����ۈ��Ĩwŷ�LE�ѵ�'u��Xž����W�����4�O��#�/ J^T9����m�!��E-j���Mk?��#�<�,T��si'���h(�J��n:
 &�g���
��~�c'~i�@;����{����
r���;�A.�!n5$�
:_��{a��zB�kA�@k���=f�����.���H��O=y�y��x��Y��p}�vIxt��h*+��/�X��������UN�~{�C��&ˎ׾0�縷b>��87��6���H˸w�Yˎ���)l4�KN��?���KV�����v��y�Э$[/([�|��K�Nż�f�7������(��tdS96Zݻ�wz�N��]�z�5�,�ðX{gL�V������a�����^w��+H�c�i�7
��A'Mr
��M;���]g�P9y]d`�/�XT��Y����h���j\"�C�Ǿ�1���2?
��]iᴰh��qWp�̓�yp�E1H��:�7)���l�{�W�;_���D�O���g,����XxX>�4i/)a���[��kj��!=�tUF]A\Şc�foC����k����Ft��{}(��v7� ��k�p��
�=�a�-��֟)PFOM\��8�P9X�R�N����$�8��3���!��x�R��IZ��[�׮�T�P��Җ��/���W�*ӣ��t-Y�?؛�&�˖�^o	{G;�����"[���j+S�4�}Ҭo����Ӑ����ݻ��SYd��&"����.��A-�7ڏ�#Y@I/�#��пʤ��gz�c��S���{vE�s��Ȱ�%�Џg:P�����\�y&MZ�9���V�!A?�Y�
�7�7_��?���>񔲝�3��	�)��=��_
�G������tǟ��W�vnIH9#`G��P��v�P.���է)�)��>�8��U�:�	�1�����%S�N����Hy�7��A�<��3\v��U8׀�H���1����Y�(��B3u�e�_Y���P��~�U�����(�z~� ������Ӂ)5�m��C�.Un��"�ت0CW��E���4���vg�RxЈMqv�)Ps|��)�+�~,�穐�nѯ����5-}P�ggR@m]K��^9ҕ������ˉ�8��ᓧ��̘i�dR�}�!�%�@����ːO�����+&Bû.�I{���P�;b�ZY�F���~�N"��9'����oP����ƺ�G5g���Z�N�D��
����؇�[~�wS��(���SÏ}����k
���e&��j\�dI?`i�{NX���3�MWO+����O�u�]�ᛵ�	�s��H�4K�����B���A7��A��.�j�9H��mħ�C8ǜ���)Q��0�?�2�U<���EOV�� ;�
�h���5�� G�ĝ�[<N��X��*+{u���, mR��n��?���D��|k���zT#�h'/1�r�����C��"ƴ�a�x/6P�
��ޕ��(�f����ǥ��L~���9鶴��r��Ř�>��	�İ1�����0��;J���\-���e��͠�ĉ>��%	�2(m�k���%di���B	���I��H���MP����k�2�z�D0ak֓�rm�$�������4��:�������g��yN���*���F��H��(;ԗ�T��4{Vf���m��֖�J��=��:H�pQ7AWT���u��w�2ȔM�)O�H�]8=d��0�w9���:Ə�I_��N��5� sR�V��#z���hzv?����y����m��0E���,aM?	�ս�v�;j��~@���ʚ
W�(�#�b����{#�g+�q��E��� �n��_w�;Xn��޺J�Vp����p�X)��璷�^ZV�$�3`\�3�"��Q�v���6G
�R�2	l�C�s$��;q����68���Ք��g�����P�D����Jv`z
T1����]��^��29��v�O+�!Q�p��
�X�P�(.�GO���WH��m�
b�*<�d꛴�#zG%I��gč�s��ja/�.���v����r�&J�8*o��<�薸>�+rj&e�
�.���f63>��:|LZ���;߇L����f��^�x2H;�m����c�R,g8��>	.�c��m�����KS��!W����^>�3[śY��T ."l~�_�3��U���$���!���C�Ȳ��~��}�:��4$�g���`٩��<������ЂǶ�q}�c����ae1�_4�I�d�"��S�A@{�͹>o�f�kS�4�6�6��bȨ���ٴw���H`I,1��J�b�M�%���oM=/�}	�K��w�s:ѫ/����V��=+��6��y7x_8ԃ����J�p�H����"x�֪�D��`(Y��1y�Q˥O���V����s��, �:Х�*Iٽ)�V�M�JS�Y�AAzPV���
��D���{��Bm�����;��Z Pe,l����&�3��,E��Q�T�;�,ѐ�j~��x�����]�i��ax��t����^S�-��R����Y���Z��Zݎ`�-�1<7�z��5��^��c�ފc�,��l�C_���X6�'ȗq�Rh�}]Jϗ�x%�-�y-�#��Y/��J3W
_GYٮD3��;\�7!��:0�٪pk��,��q,���
�׺��څ�,`v9+��	��6Q\d�|k�ǭ�_���ۖb��.59/a�V?��U�@Mx�h.=pB�s���ض�Շ�Pg��e	�q��Ds��z�Z�0�ы���k�����'���C�������B5m
�X��$�(����E��O4�D�jj"n\���(��v���s���s��R`6�2pؐ3�u��Ĕ��X��"��O���B�6��y��t7���J���H�Nq�w`�A,
>��{\�a�G*�<]�)��U֎L$��]=�]Iq�^��)�>68����-s�g`�D��i�J"�u��Eq	Ⲫ?���w}_�u9���'s
��.�=_���)ٟņc۶���zᖚ�v��.]ˆ ~lӐ�p�'4m�i�e��%�P���NUa�ɶ�l�����0&v�+h��V�%��E����P�	�q�����{ٔ�����lNl��UMA�	l�7�<T�z wf���f!{���&j���^P�e���i�]��J�J,����K <�G*�uG'|��)��@��R0��.��w���	j�t�Ă�)fBBpt#�|N���)�%���$�nb1Z�B$���_�������$���E{�[^�(]a�/��<�60��E܏�I9��:A��x�J!#����~�<���A��QM,������|��T��#N5�%:�_��G�2�W(�5�Vɫɟ��P�W�z[lꢊ�����hZ�,�ZM����p����D\.�c>a�\�0RG�Y1c&�T�<׭��i���l(75A��[X�P攅�^Q.�g��H���+;�DN[ƕ�G�o�'�{s��tv��D�S6^�Sv��夙��nJ�?���?&��<�?�5%�W�e�����@4}����	9�eB�)4�sT�&9n���ו�~��o
h!g0�7C@L�~�Za=���)�>��
��,�e�<or?�4r���{3���:���6��4�j��C+ù-$|�c���͖m���DQ�ձh�Vf���an�-e�IQ2����=����p��Pt�;꾶mb�^�]�W�C�Ƹ}3�r�39>hWfWߑ�K��O�Ee�m�uQy�z���=�s\iJ8rO�2l.��q���e��҄�İ�E?�o}7�ڪ#¥*�w�&s��l��������A�3�4qGG�fTp���Ү�3����V:�ʱ�,+І�.P^;4�@�Q���Y�7�rxc�[�$�n���4����nC�s,!����xb�ЗZ�	N�x�]�]6��h?̟��X�i�B�'2����"I���rT�]q��-	�����y�۪AvN��}�}nj��bH-ȴ�!�$A�{&��ͽm�0�4��˔��%�5�Y�}=M8�ьmXJ�J�i@��`R�س���頗�H������2�Dbz�&Ж�=B9oj���"J��}`��f~�x
F~�v�K�����x>
V��:_���˯���Y1��J�������6H��"�bT�1;����	%a�p���T
*�a:dB�2�8S%�B��8�<��!lk�ij�[8����Bߛ�1�U |[�h7n���_�w���i�W��f�Ehsz��8Fb��j�'8[��
xh���V8䖓�)'Pd*n�.��J�}z8I.0W�L��{��P7�y�[�#���4��0��s��
@^Xl���M�U��vaXf)x(�\7��(�((ܲm��9�FJ]��i
7l<�Ʒ�J]�*������V��5-<��gDЌB�G���RYu�Y�f�]΅�O�l��3���}̀3��	�%�U����[�䏌�"��
���D�+	�4�VH��y�{�q��������\	[1�X�iw���C�a��l��SI�[dǚ�%8����e
��t�����_�sl���j���B�ؐꍋH���Tť������^X߹O��Ż�ڱԏ�
V���]�(
#��{[G&jn\�T�Og?��x]fݍ(�U��dc���󅣲������|�%nB>x��)��`�s��'��U�����d��� /�l:c%�(r��P*jwJ�F�b�y鄊���G
�������c�����]R�O��(M��O�����dX�b�����
(��M3��'.��:_�o�.QJ
�P�ϱ����F}L�̬�G�ҙ���%C#�*�;�`Ga��%j��wF��O��+ԙ�&\��X;R[A�6}�J�m���+�,�ԡ�[�SJ�z�+��C���?���X�N�&�7�gJ��_r��%�Y8��Ph4�_'z�]�ac�C6u��JqF!t��*		�kT9L�g��'c��F��n��(����Jl��_GYf�	'cO�q�J�g'����o�|�4/h����:�{>h���G��E� �!A�0m���N�J��^J��8&霶Y� ��$e��Q��v�U7@)	- x��}g-�'�x��=�]�5ea�0C�[@*�\���z��%�����@�95���H�������N3q��N-�6�l2'p��v��atfx��N�f�w�8�L���r��o�%���,#e�
Kq�d�6xc��ʥ���0� *%�k��E��\
u��
G�p�D w'`�>��f���,IY�l`�ԝ����7��
�H҇_�lEO�0��Z�f��&�Gb-]�#��~�L�[7�����a��ζ?[���(d�Gx`<�0�I�q6���~��L��$n�ץ1"c3U�d�6��!�߂Od;(n��l-�i����H��z�{J!2�.�;x=�����]���z3(��#޹]�,F�Nժ�F��)l�@��i�nu$}f8�~
�k¨���O�������ն��y����ou��g�_�_@3�d�!,U`���$%��1I)��	SE�GV$�&��"����������Z]܇�b������RK����_.:)�\���((�Ϫ�Bkְ�2k�$�yO��t
Ĺ�ޕ�w��N��U>b'Q(�w�]��cTX�Ѹ˴���c�~ި��(a�n"Y�x�&z�S�ᐺ��j.��@qN{:���W���N꒿h2�KZI��&�,.�����-��"����\Tƙ�?U-�_Vvq1q�KPʙq�t�AI��>b�#�b���B��~�Iܙ��`ʷ���l�*�#z�ꞙO{2v�
a��A�wmD1���Wt�h�5{���;#�Ӽq��b�?��{��/�]��B��<����8���2z� �k��|��*����j��U']��KQ�������_�ET�滽+7^��xv����Ⳬ�^GC�}.��i#z'�\R��|�!?jR�:H�\�2�嫊�J1ӽ���ߏ�ҫJk��U"8��
EX��$�"��/���J�Y�*�|ܸG��L���<���8��г�R���"h
>�r
� n�Jh��e�!0���TXơ�.p ���K�P����r�e���x~=�H��û㜠V��u�i����Ī~x�5Yhɫ0> RfJ���&����(ڨ�u^&%'�c�`M�|�k��1�S�}���U���4�w�J�B�
�oq��5�㿏[���㶹��G�3sj*s真C̏�O#����%�p�%�u���[����%�Qrϵ;*�3=
dȦ��i6mgJ?�-��K���Y�!����g�ɰ�%�Q/\��d�h��\�3�O�1F�൤򘒺?%BrW�f����ez�ݥ&����c�6x�Og����mV�y����<~��_4��άiy���,�:���c��[���((J�a��ΤٲP���nP9w1�ʬK8�>;i�쥾��ڴlK�!����n2DXwl�WE��G���G���\{���
��,[�k��(!���[�,̣&����s.�p�2i���5�n�n:ɳ#kt�K��UL"���;�A�L!M�G1��{����bADM�����i�J@r���T
��dzO�^Mi�ˉ@P�����)�{����ħ��7�Y��{��A]	2��k���������5v���ES��ߛ�m�i���ګ���X��_���Q�w7b(,X��jY[�2��g����˘P�[y��w���ʘK͞���%Jt@+��6��u�fp1���(��j�Af�xˆ�`��
���n�tr�x�,x#�
�kz�g�Ǜem�ۺi�U�X���H����eY(���_A
W�����h;r�*�c�Zۤ�&Y�V�$�ߨ�u�j���Y��%��.�.*4�[|H�a,S6UF����4�x$���@�� ��t��MGJ�>QP�]IS|z�KM��8�b^d��h?f�x�1�[CMx�1Пw�ۃ�cl����rj�����	6�[�k˖2��H��p���:D��ū�1�F���]�n�	I[o��y̱H��w��U.*y�!�C�y�T ���l3-��Q!�`�(��P	�-�������BM� �\��ϻ�*!��1\�����i�e�,R	�v|�h�~
��i�%��dR�K��Jy�[\�\f`�/�X��p����������FO���-;njgu�Y�B�/O&_���UX�,PΠ'��'��K�B�3n}+�ߣ�}�u�9�����"�32��z
�C4GZ�;�P�e� מ ����������oM�.d���:wd��k����8cB�r("�����]���,���=]����O��
endstream
endobj

63 0 obj
11937
endobj

64 0 obj
<</Type/FontDescriptor/FontName/CAAAAA+NimbusSans
/Flags 4
/FontBBox[-210 -299 1032 1076]/ItalicAngle 0
/Ascent 0
/Descent 0
/CapHeight 1075
/StemV 80
/FontFile 62 0 R
>>
endobj

65 0 obj
<</Length 609/Filter/FlateDecode>>
stream
x�]��n�0��z
�C qIJ`�O������
�%A�~�jv���!���%�٥7�v����oc_Ô�ۮí��uHO��v���i�)��}��$�s�������/�I�}�v��G��n�S��d_�&�mwI_~n���x����)͓�*m�y>�s5|��!Ӭ�C3n������B*�6D��&܆�c�]B���U���WI���-L9��_�8��94����Eu��Ro���W]:���T-9�1�Fm�������[2�w<S�ߩ5f��C��zM~�xC~C~y�&�Ž���&���/�L�(��_h.�E��_�]��͐ߣ���B~f!���B�R5�K�+�/�K"��D~�M"�:��B~f����ȯ����=z��#у�=���Ϝ�<��,�8��ҋ���^��̖^J��ҋ]C�^�M��E�Y?�GM����ɫ�oJσɍr�7��]�}��5j�D��f�><�]�	�tч�Ї�}�p���ãN�>��Ї���z8�[=���ű���g?,|y�a������'�E���G��ȯ��_�~����8=0^0�>�VZ��qY:$uVaJ�]�;G�~@���z�=�
endstream
endobj

66 0 obj
<</Type/Font/Subtype/Type1/BaseFont/CAAAAA+NimbusSans
/FirstChar 0
/LastChar 88
/Widths[278 778 556 222 222 278 556 278 333 556 556 500 833 556 500 667
667 556 556 278 556 722 556 556 191 278 556 333 556 278 722 556
667 333 500 500 556 278 833 500 722 611 556 333 500 584 667 611
778 722 722 778 667 667 500 278 278 944 500 556 667 222 556 556
333 333 350 722 500 667 611 722 667 500 556 278 556 778 889 556
556 400 556 556 222 1015 737 556 1000 ]
/FontDescriptor 64 0 R
/ToUnicode 65 0 R
>>
endobj

67 0 obj
<</Length 68 0 R/Filter/FlateDecode/Length1 1720/Length2 10080/Length3 532>>
stream
x��eP�Kר���38A�@pw'�
��;!Hp����n�5���Np��~�����}N��w��S55ך�}_�zu�QI;9�iz;�8X9؀�e3wW
SGWq'{��P886�n3���#
��@� KvUS���+�W��������?�j9ڸ���$�@���:F��
l��B������_�`�������k������������py _|@��������Va����+�K����ǔ�ߦo���h�`c����
r��w�]�������
���0�M�Q���q��|96� /��������pvw�X:�Q�R�����p؝�.����
`��x�n/��7�ص�~;�o���
@��+A\�M�_���K��qq�m�,^C#G��@�|@�W���+A�L_	��J9��"@�4^	"��J1�W�h�qB�<_	���J�W��x��E�� .�{qqx%������k� >֯�W�^	�c�J�W��(���� >R��Q}m���+A|d^	�"�J�W���y��
7�F� 6���ׅ֠qC�<^	��jo���Tn���kCB�,_	��l
9ڃ,_����`+��!����G�C4�_	���JC7k0�y ��N�=�#��l��Ow'7�+����#��	�ym	^���+A�^	�(�JCSWss���k�����&����?����
��G�y!ʠՃ�������zV� Ҷ�Qu�\*`Ws'�?>��� ƚ����kl�ݺ|sg{��K����JW3Ss�o;��
l����	�U7����ژ�eȝgo�_�ׅi��4���j�m�?li��d���Qy����>�C2\���[�}G+��OG%�Y��t�b��b,���8jy�]�`j@����ΤX䇉��/ocd1�r�{]{�+��(5yμ!3i[�T�]�Z
�|��,���-�|#ہ�M��b�48�P芰�qҖ�)��hX�e���$�}ظ�Z����M~�_.��Ԡ����/�y�6L��
>��Y��hr+)�p�cI���Hk�t.*�Y"�Q��>��>�#<�O+ψ��~��J���s�����E�?���J˂��d޽x�A8��1���D�m;���Kl�&�]{kq�f���G��Q!�h��d�/�$7���[6����mZ�c<��
{�7��$
H��V@�6��n����ƴ��.�}��(<.�U�6q�$�Zl7���;ELN�����'���-""��l������z�8f��O��:�����
�u�jK��pC����_�R
7gw���>�I���"����9E��-$'V���@�hξ0|��.�T�(�:���d�C�՘��8&:��V+�{��R�F������P�~n���G6"K��UY��+ϯ~	��q��C�vy���pJ���ƚ9AP�=�|�o�Q�L�v��P��;\i۰�e��B�8��RZjJ+;Lhm�Z��fq���A��Ęܫeo�̘��� ���b3$��^�@�!9�l'���	�^|̖���
:�R��3�T~�g&��-L����jy��F�v`w��;6���ɚ��;�����4{9����s�Xj��&buW��Vu�:�V����Q������U��-jj�\߶
���Q�'��,�{�}���/(��,\���k���0�tK���	��ds�[$����O���l
8�9�q��:3ѥv��
�ʷg�N�h���s�L�V����g��گ����<����ǪJ��J�)hXA<��[�$xԒ���.!���t=yqҙ�e�/��L������!�9�I�,�X��E�d�UW��� KV�S;���	p�侑ƕ���l����f4��3������{U��P��U��[��{R�w}�9�D����4-��yn��c��ޛy��h�1���c�2(��Z�"�?�:4�D��x�S�R
��\�T���|\�ă�Q�
�J�E{�5(�y-��N��ɋAE�����^�~]��lN+0+���(i�9'ڍ��4��^ͥT*=�0��[�,V�Jr
�E,|���P����(�P�OU�귤z��$JQS+̲�+�0���}��r����ޘU͂&�{��Tj-��ר���K�G��#.�T�ʷ��%w�OJ����[O�p�V8��7���)$�V�˫�gĉL)+��b����[��~$��/��'օx��u�>�GDZ���0�x���S-Tᓉ~�.�iwZ;ki(��m/�V���
ف�/�ـս�5�sZL$��R��ד�\Y7��۹��ϩ��P��b��ɋ�k2e����ca��{�:��tm��ȁ��R��(��wM�!��|���s����Ĕ�z�G�ʜ�8i��4�>	�S�SA������[�r��Y�-�\E���`�[�*��҅��A$|�ےz�=Q���Fi�O�*�񼐻UWfZ������1�A���Ok���p�d<��źX�n�Q�
�i�F#�n)���*�����۹�xkθ��Z�-����*���1ip�K�0�9.��b�SND�S�(��Y�A���94��G���C>B`��c,}�mJ*n+�u[q�\��@�Ep��u��6~|�|f�y\0��ӌ���
_�2E�b�y�oF������ڮo�'��s�Zn�'N�|
6��{�b���g;�
�3�N�\P&
v�{#�r�[�e��'��u�m��H��Y�-�hΆa���c���G��á{��=.�p��B�5b���v;����_�6��u̗9#���#)�yT/I�Z���<�|
�i,�`�S�)8�P[�K�Y�"k�Yb	��/�Ɛ9iR���[����&�+�^����D��}�V��V�˒�ˊJ�x���M6k=�?}en����y^nV�%�a�H32C�򮷮!��0�uTLW�r1�. @�E�O@���Q��B�v�1
Ae kO�.�v��o>o��Ay@CA%4V�ji.���jʛ�7k{��~�#;9?^��|�T�/�?�>���h�b�joU�|O+E�>�M��Jy�\{�i$�9�^�g��;�7J���paM��#_I<)�V茀��y(-��w�n�Y��:8��w
W�A�VWlbœ�s](1�=�2��V�30��I�|88��G���k�uc2�.G�=�Q59N*<n��q��.�~����7�T�G�[��`��Gk`�*2�����8tJ�Χ��L�q��|�w�C��}�|���#�^�d���G�.V�sy��*�2���Ge�P�V~#�z�]J�	;垷�R
�YXp}��ք
�k�J?xk^=8$d%�W�#� c>�z.;G&�n�\��]}wՄ7�O�H���"�!��P�尢q�,��[V\�Sg�F�\]�6��zg�f��4L�ы���.�D��/�'�IN��!����L��މ���Ρ
�	ֶ�U�����~���5�ňin
��1&���L�8�*���i�!Og��,&;֮�,�T'	���/&h������a�ՠ�G?t��@���������ia1��7Hjڜ��;a������e��	��u��>k���'��������f�D�G0Y���lYј��^����D�����<�UdK�����2�Jn�g��5�Nro
u3KJѻ�eʟ�	�� q��`W���&]����O|0�ޫ����v����1��o�U�����0�9���r@���z��K�j\��}��@��q�_u� F��t��ZZ[�_Yq��K���Gv��h�_
.�Ērԥ�\؏\uޞ��xW<
���}s�{�l��T`�Ƭ��J`��|vi�BR.��ؘ.��g��l��tuT��{�J�'�l�U�PE���H���E�rc��dcJM��%㡚���4���@�������{2�t}���
0���4��* �7cT�I��n�ۚ���#�XQ�8l���e����k���Y���I�q�3mA�p1I�M<.SpF�b�f��ݟ?"�$�ُ]�]����0���M~�!���O܌�k37�t���sz���=A��7�q�s������D��qwRN�Z���wr1��[��Im
_��c�R����$��5�V�3�Sx���y8%�5%wE�������}�
{�WKO	�KX��ޫ��	g���y���á�yڎ��KFw�ٯ�:�/��_���u�
��!��@?�B�S}yƈJC� 8h+g��-%w�G��6���#zT*l��H�߈�7Ӝ�B�.�v%h�y��叄 ��P6��d�b��-7D�~�lR�Gd�hpa@�OQfZ$�����=(�G��Q���3ވ�ȵD�
��icA�x�Y��VA����uތ�/�?o�PPp��?�a�n)xl�9Ҋ#w߲E���u�ݖ޲�c�w��ߧ}jt���(`�~�ypo}ބ����rS�n�x�m��\��>�r.�Y�̩dq�J�=���1Ί�v���[��$�m�Y�xz}k_���~�S����l��(����=�-�]�$�)%�qw_х2�\�n��J��*�T���PR�E��q���o/��׫O5���|����,������".����i���P��5{�y��
��j��&�
����v�u��M�=M�H��y~�KI��v�k9M��k���	��X-���H�,i�1����͚h3H���7��i�sy���[�!
~��f�Fl�l(��6�����]�U��^��-,/�S1���&�o��tC�g�Y�8��rm�yOx�n��M=�P�����3g�C�F��_wD�Je���;ЃY	F�f��}��^���f~��?����f7�K���=��W�*�lz������t���V�}Z-d�
d&JX�iP�w}�Cs���b��5�����(s�,C���P��~��4����q-ȁ��.�0�j�+Qd��At
3>g���%��r���`_)�s�w�	R\w��i�����G2�2zܢȣ
���J�*&�,$���o'|LJ�2� ��J�ݟcJ;��e�"�Gy�Ğ��1C����ƿ���	E Ù%,�	�g��O����g��g��e���#��#��|[ŊSa�����/?V�1�E�����|��L�}1;��X\�O�;Z^����;��2�\g��h~z�
�l,T��T.c�
��'\)(rSk�?q���(�D��^�$ꡟ0l�B&�?�:O7ힺ�s#�t��:�9�/���t����B+��A�2��x��!U�L�-
�y�'k��>��¼�P�'�u�ٌ�go�.�(y!
�N^/���Z.-�_R��Y�H'�T�q���Bn��O�d[`�,w��)���n�3�s}��	��C!�|%0��Mo�vd�>� [�C��Z])�O@�Ϡ��0�:��q�!.`<K�����{
U��{��p�����F��r��e5V�|�{ѱ�m��c�#0��%��ų�獜��j{۞:8(K�\�MS��^��c��W?�g8����C!�%Mϖk�>�t�>�
a������ŭi�:�iĢ�3y�>�VZ_��i4�T���/]VI�F?����
��θ��`���ӋA�+_��e����R��� ���bI���h�m����X�)��Y�.tGl|I\2����H��>��cX�H�L��q= P����z)�G�.�fG��I�.���=Ռ��y�n5�/,�#?{�U�4�"��u�3*�����ְ]e��VT�kl�O>:`�b5�U�5[�&�CVB#L�Rۅ�m��w�x_4�՘����y����r)ը�[�$
l41u~$ �/̐ާ�����na�Q_�X��=cpx�M�6�`���D�5$�f���1��Gh�dc�:�1�g��J�|ʒ�_�F��!�����m��51�3*eq���ʿ#c�}�6�V(b��Cf�,�&������B���<��ā4y���tRZ�"S��y�7�>��CPr��g[�{̠2���<��lf��f��_Fj�M/v��J�g�)�G��!����0RAC{1N�����4�k:������R���#'f�|�!Fj4�;���B��f�����7^d�������Io�$��_�`��nU�ҭ�q��1Zm散&̊�zL_�*�&��L&�	����o2��w����N6�<���F��e
�ܵ��HyX+m�H�.0�d�A8a{��s?W�aP	���^I�G�hq�O�Wf����������(��tw��呎9�'[���ٔ�b���$]ǸM(����r�ҡ�?e�����Lk�lܾ�Q�F�t����˨��rNS�G��J��Ց�zM�6��{�e�26�h�Q^V�Y�Ik��I��Q�òS�����z��
����+Vi��u�}���M8#K�I�ƣ�C5e���!���@��[�/<fzy�
�y~��}L�(��������ўh�1r��5�r��i(�8ʞ��~��VFH�"ao��jy��G�͎l�H͝�Z�b9~ �F�a G!��pZ��5
c��T�X
1�E�*�$���ѓj���e���c�H�՜Y��]��Vm��Au�%�@ۚ1'��>��S�z?�)3j�'�rDΏ���S�7)�^�'�nDc��"�l�$����k O��Z����1J�f��Yu�f��2�/���~O�5�wa���K�ƈ]0�V+C����,�����vH<�4���&��]��m�ӿ��X�c��T�U�z-� 4�Z�D��kJQ�ה�"���Uj�(�V�*�j�;��1���-�� ;q9�N��";?�,K2�*�B{�]��QI}�t��B��Z�U7|��YF
[�g�P앜-m��4��E���?�\�[�UE�z��H!����Lܦ������z�u�Z�h��{��G��,��t�3a�d���y�N%��
���W�!(���2�:d~��w�R?kk#�+�ꀞ����t�Ԃ�4��э4��c!�`Je�����Q���~p��U**��N�ÙEŞ���u��LV����YmXLp�vc�U)kS��r{r���j.y[�-�)�f�:��|mz�K�����D#�	���e�u��:~
El9e!����Δ��/�Έ|��sq��&��o1�E	�9GX0�E���-��g�2��FN�﷾��$f��?�@�
�ZT箦�C��ATz��I;�"�n
���ĥ�����Է��2��f�w�@�p��&������,�3�m>�t�%����4Ly=��#^�jT���Kk�uԱԺj��/M��DA���k�4�w��-�z�(�=^p��l1]
92)�D�]����CSn���D֨�*7�DZpC"��?�շ��X����$�1�ׂ4�=�:{��q�!�4/��`i��\�po���^��h�fvGa�E�C��(�b��Uբ���g,��⑬�'"5����u��Cv���0IA�M��G�1{x_I|o������I�O��!n�V�!4m̊ǐ)�p����@��[��z<1Rqr����"��{�P�4sw񼋂�I���[��B�2eÓ���M����4���B��)�I��+%0�l�=cZ\:�ꧏL�;-�����(�$w)�\��SAd�A���1���9���&��yb�"������}�#o�f%�^׊�qB(�/��
Յ��B�g����j�E֘D�����H���S��LG��_b�Z�Ч�Y�n��?i5q���@���tx��(_���������ޜ6�B�|YF���_���]8v�Ç?��$��^+&�c/J��_��9�sKS���WI<.Aۢ����v��P�׎�K|)�o��ʣ��̉5u�T
�[/u�ooջ��DT���4"!����^��7gi�s�رM<xuO8�����џ�K	��;7-G����d�N̔��x}�8X�B���x�_bH��$c�·��w�1n��xP"�@����tY��kni�<��'����ɽ�2�=����[y�"��P��nn#��>����]������ �!j=������,oW��AW��Am�������D:z�=-�(�(�����A���y>���L����t_�}a�z��Zv$ҸOI���t2Fœ��NF<�Փ?��4} ��"�(1ʻ�*X7@���u�le�V�����x&��m�L�Kˆ�5�d��Pq=�Њ���������3
+x�A)T��Zpð�)Q�O8S��ޮ�CB�
QOK�#c"�	t�J�<��gY��O�z�PE#���s�����P�R2)�����4���ɸ���Y#�q1�6oe�%����D���U�S�7����Ah��'��:w�j(�_�f�Uᄰ-���0�nc��j��7�Cz�v�LXB3L�,N>����F�D��+W[�q���{��SA�۱[gg>�	Xg��۩�9��'ES,������P@��<R�("!���ݿ��cbR���.����B�|�]:I؅��t�>�'�k��R��j��
.�p�{��}W}+S�N��2���1��G�^������L��1���=�>֩�
\�E�~�a�7SUҠ�kr\Ψ���b���F�47���x��)��I€�%W̮�-�c���M���8�'�	�~隽����s���7H��
3��E�~lo�ͅ"�Թ"��z:iJ">g��jrq^�!�^����u�K�H2���䳀�@U�\��5��XkM)H"��p���SU�4w��`m�j�vxNub�f� ��R��:a�x�Q�{�'�O~�mZ�̤)O�L'��•3�J׫,e�%��]z�LI�3���-�yiP�-UcF�}f�o���M*d�N�EU����qDz�Ab�iiJ����U���#���P%�<���U�QK�ꅯHK�y�r[;��0�&�ԟ�~7��o�xx�����l�'��
���a��n�G�5�d��.=�����HZ��懎�/�JӒ�	+�g�H�汗�8E^���DG<{S��L�K�H�N��t �]���~��j�����H���$�P)Z>����b̩���*���ы9�
>e ��e3N����Ȃ������A)rٺ>`���Ў�V���U�%J�MS�5�b@Ps����*J
��쯸�8����<�DУX�����������<SlDѴ�Y��ˋ���&�
��A�|��Q�>o�����kf�I���qL���$��͝u��Ǥ"�`�]�����=�o=�m5��A$c
�y����"Bc�%�������c4�b������ڟ�&ɓ�㞉�Te��B�����I2t�
e`ܰ��B�!���饝G/ٕ�W�y�Ňv�Y}��a�Tjb�dcDWń�&ȼ�|�osZ�'��"��8d}G2#C�"�	�-�?饝�;U�rc�+��~`�M����u�)t@�G0@����e�Ȓ�C�k�l��:״dU_GD��k؈c��fBO���]�Ƞ�2\��cL�����osZ�H\D��y��߭`�R�㪷H�ѵ~k�e��3��HF�@��B��vN��֝G0r|�P�xYI6���i�99��e�Tk��c-��|�ɉ3���w��`������k�Z�a�D~�1	�&�y�$I�^�EQ�3��w��M�g@�NL!�h��C"�_�;X���M}}�o+���<[$�&p�8N�U�g�D;c!��ي?7�
K�LI�N��,�c���d���Ϭ�U(�T����@��&���oK�ϛ��>��j.��V�ͼ��6��l|x�&V�vU>8��9Cz~�[ؔ�6�}�%o�ux��r��&����(#P�����3RUn`7���HG��+�9m���^R�b���}G�l��Ʊ�����k#:�.��	W7-[�4��g������2�����z����x�P���l��q���e���f�n���/����)DDm��[�[�E8���D���5���}K�<z�Q}4~�A�VW'��;�.)�,6��D�T�uV-D8���3�����q�͋��(�6�g�	��8$]���`Ɂ�7�"��N"*���"N���+ܱ�ٱ%�gΎ��NE8?pg|2��n�$������R2X����b|,��fm�f~}t6L:[�'�b}p4�T�uŰ���yH��@�h�*������� g���7~��+6nO�Ir�&�+��mct�)�f�H:�Ѣ�m4qe���۶��M�S�*��@�r�;0�#]��0�,e�����w�c�0��-$AO�j�-_��	ę���G���=�bZ�b�9�n]ڏ�J0;ɡɑ?A����}�*zK�cE>{�������3���7Y"!S�@bx���C\�<��9��?�cdL׶@*�"a�Q6wG/��cO�0�%��l_�e	`UC1����_��FcC
𳓐��~�G�R�[�C5���b`�F!��]dQ5�N��U-�������1�st*b�Wt�����‘8��j҅w��\5D1[
����蠚)��斂���+�����
��p�ѰƐ�9<�i����3;e�9���<%�eF���x�H�7G�^��t?�R������ę��(����^�(�]X�
ܥ_�#k8�"{_QV(�{}]"et�'�rj�[^���r��7�N�O��xp%�)�Vʀ�3�޾�i�E�l�I�{ű�H��X��(�`?��il�؋ź">��b)�w+	}��=�Z�

2�tO�b(&d*����L�2힅�ɂ�ӧ`/����~Pd�T��\�I���ƿ?)`2q�M��^<�qt��_?s��Q���̌��u�ĉ��M%�c|c�g��,&�v�	jR����Ubԅ�?|���wL`n2�99����{U� 
endstream
endobj

68 0 obj
11017
endobj

69 0 obj
<</Type/FontDescriptor/FontName/BAAAAA+NimbusSansBold
/Flags 4
/FontBBox[-188 -307 1069 1071]/ItalicAngle 0
/Ascent 0
/Descent 0
/CapHeight 1070
/StemV 80
/FontFile 67 0 R
>>
endobj

70 0 obj
<</Length 576/Filter/FlateDecode>>
stream
x�]�͎�0��<��b��aF�"e���E�L���"5�Y���s��J]$:�c�;����0�K�m�cX�s?ts����
�)\�!36��vIO��^�)+���㶄�a8��UV|��n��ȟ6�x
����܅�.�ӏ�1>���+\ð�e�^�]8�u>7ӗ�
��|���~y<�)��)�V�
Qڱ��i������r����u��w/%�����f�V�e)Ѽ*��J���B�+�W]t�q]���=���Ao��~SmK�jg�wW�;�u�=5��$3�
�+�5�t�Ǿ��^5��4�}
M�
�L��q��`�_#�!��_�l�/��+�I���-�+̵䯑˦��n��52Z��4�+�Y�xl���C�J��_��d����M��}��QOK~~K�~G~�>q��w�_=����o�ő_P���J��A����f��:fp����!�c����r0������/���'��q~�ل�fp�g�����K:��zu�{0K���H�T���u�����p�B~�Og`�#O_3>w�G�����s�B��һ�F?����4N����.'�
endstream
endobj

71 0 obj
<</Type/Font/Subtype/Type1/BaseFont/BAAAAA+NimbusSansBold
/FirstChar 0
/LastChar 80
/Widths[278 778 611 278 278 333 556 667 389 556 611 278 556 278 556 556
278 556 833 556 667 667 944 611 778 611 611 556 722 722 889 333
611 611 611 556 722 611 667 667 556 778 722 611 556 778 333 556
278 722 333 333 333 556 611 722 722 556 556 556 238 556 611 722
722 584 611 556 556 278 278 556 611 611 333 584 500 278 333 389
333 ]
/FontDescriptor 69 0 R
/ToUnicode 70 0 R
>>
endobj

72 0 obj
<</Length 73 0 R/Filter/FlateDecode/Length1 13932>>
stream
x��z{X[ו�>g�#�B�e���8ǁ�2(�	�vl!@6zD0u��Mm�M�a���8��M}gZO�m�8u�Ɲ�M3i�m&��m'�fz���|�&������ϑ�q�u����9���z��c��G"�����%@Z�!_���J"���.�?������Al��ϏF�B��?����y`lbzt���JB�U��V�˾�O_O�AHN��<�_T��?�W����ħ���+&"~�鼿����i?����O����/�}!�jy����	)wE#��f�
!7n��ј���G���ϣ�p���1cSG�<�N�e0��ٖ���W�U�k�������'3���4w�{ǎ��8�y�CB9�%G��T����I�fkw�{��d���'�(yUxG_%3�9�#ry��$�G�f|?G~��b!<�:O��ב��q�6��E)��G���y�x�3"�o����$��5"��z����/dg)����J�
f�1�y���A������*�)�=���a;�A^ϓY}%�Սr��v��͸���uv~J���������M~�l$�$�{��q�����|�'�!Z��p����v]h����"�;�[<�~��N<sȟ���F��(��@;Y����Kd?wu!�=$N��|_'
�s�!YO�U���ֻ����9�t%�^:A�NdOK�W��
	%��	��Te��*�q���sl��N��j׸����w����8�j�#��qeN��J�'ŭf�-�{��{y�4�=w�Fb=w���5y�r[U��|\ ��Pr�]eNo�����j17��!aZ�":Rޚ+
h�S�I=Ǔ!_o�|���w��y�����r�����_/��rFy�Y�c�Tϕ��谑Z�f#����W"ߠ+��)Z~S����E�5U�7��9w�MՕ:��Ϸpv^o�𷲢�vS��9�mj,�>�jÝ[������]����f����Wk���43��!����}X?={?$Êr���?s������~�&!O���f�?)���f�Ɍ�@���`�Ӳ�u�*x����1�vSuMcA>S�\˴��|+�ﶳ�z�����S?�l�������6qY�����}Y���ɷ^��,�$v�b������n�#[[���鉘c���֜���̝�̲��I�9/Kf�Ao����sg�gΜ�m�m���f�T�����CFo�;��
��+8���3�o^�W�����?�Ɗ����F���2�=�ʛsݝG����WV���1$����3�&�)[4�MY"�sz���W�Y�!�8+&�!K��Y���d�L�wΝ;KU-l��2U/62t3tM}Q�r(ף�y�\֘Q�W��P��pz\�7;_7/l��0;����S,�K����H���rⲢeD,*Zf22U̢hϷb~���.��� )��f-˷[��Ap���l�VĶ��J}�ֳ��5C[�,\�< �q��*wO�t=���]��7�S��Rn���c�g?:���`��Ñɢ�~�,w;�|�sT؃�W�-��`�q�z�r&��+����rM1�TZm}���ְ�m�((lV�����%D��x�0^�GH����"E��HI�4Rf��m�n��2B���N_�,j�L��:ዉݯ8�d��c�y��OB�]0�/���=zx����Һ���G>:�z��_��M��}�B�n�?�p�-�G��N̻b�p��9F�4\8‹bOC�`��9��<(�ņ�%Cv.��3���,�ŚC�ٲ����Vn�2�=���?F�c�"ɂ�T�-r�B�@e%
�4�SPM3�3��u��g�wϿ5/m�������t'��`쨹k�?��?�y���hP}�m�%�n��%��1���|@o�r��d�ʅ2�m�6��
35r�$S��TϑR}�^�R��gΠA�͚s������_�TR
�0{,��,+䰜l��1�셫�j�&����4sn�������07��I����i2�M��D�t-=<�?Z+��W�(()�!��$�!��`-Y�u�n�0�F���F�o/,X�-�`0�j�-G�ƚ���k%b(����f��?};GߙL(��t�	�������\c۾i.�7CO�'�F���"�+vo�ޅ���k�Nm��$@n�ޱ�?)���D\�@\�I=��V_��by�XQ*�XHq	}r\6��&�`-9��\�n����ci1Hi���f �
3�����+fj��b�uT��X��Do+��
�C�/l`�#��Z�=��{�i�^�(���Y^��(�x�o��p��֛׮\S��zm�Qr�;����Q��짖-:Z|�$�������p�|,��c��J�[c�J�r�������uZ֮,oZ�N�t�'���=cC_�Uu��{�γ�?��x�f��Br�ˑʉ?���o��-������Mm�G���-��g��m{��g��N��<��4��YY��o�~�Gv�6�D�I��4ᶐc2 Ħ�ʙ���Ew�hɶ���<+�v�3�;1����T-��4^FLsWY
T�M������JZX����+~�m�=��W�����i�|Wk�~���u�쟽���������̻���T�[�l��Z�o�JM��h_\���A�ace_�K����\��4�˕��ϳ��r텺�2��TVM��	6���2���W��T�����¼&.�X���:P�ͣ���57�:�W^�/q>�����6��y��papp��{7
�Sl���.����g���]������{	s�Fwr��e����:ѐ� 䘰a
���eb����d$:��7���\,�?�U7�4��Yj��X�����rZ(���z�V�s~U�����*�v8�}�����o��BU%�+�Mu�%�)n��g�[/�Ϧyk9z8�+ӿ^��}��c���r���'�|��{J����>Y���a�0|ö�[����SO��]���R�2�n��EW9�������s�mx���~�+tb�L!�C���t���︛���K�f��>/�*̉�bT��*�XI�&��v+��	�s}D$x?'�E�I�M[A�V�q�*=�r�6�edRk�~Pk�x?��u��<���0~����M��m8�7$�m!7"gN0`��Z�#�i�����
�
d���Z[���Z[$����#s���"�n�m"-���Ϋ6��X�����"��Xpl<!���J�k�4I#���`"��ɾ�Cr����sbB�P����rlR����MI�?���q���`X�&G&�~)	������Kݑp�'�I�K��O�$���HXj�oZ��PJQ�x�h$�:&P��D"������d}<�����HlL�ˉ
��jL�N[+��˲4"OD�j�Oa_�Ѹ���I*�4�ƺ���<���ATQJ�|9��"�K��}r,�3$�z\��(k,�'�C���
F�R""���R������?*M)㲆���HN	��A��q��ARQ���/���>����!9��%�>��	�x��H��hb
1��e���h,H�e�&DÂ#Ʉ�tX���^�O$T��`b<�L�2��&���T(�m2�������̿�qG����Iq���ATU3�h���R�tL��x$t���d,�e�0���O���	:�b<�!I
�G �#�b4��o$2)3�(b
�� I���(�Jt!�9)>�C�Fd
5T�ܷ��H�"&�"1��fK��<�CA��R�gC�i�?	G�4�|	=l S_ �,W���勡^�	_�	
���X��161��E4B}~d�+R�ėJR#.���`����.��GT1<1-�:���_o-m�)��7��1�dՀ�H,�*ҹXAe�&�
��6�N��3#2f�D?P#&#��b�f��F1�|#2�P�G�K3�KH�8r�ËqAq��ဦp��R�Zx=��#4��먣|�� �/)¨Ͽ�7��a.bUOՏOX�Da�B�Q�T�K����/y{7�:=.���<����v����~�Ct�w��KH�q��K�$gϰ�����\C}��+�z$ww_�ۅc��vwO������K]�nw?2��eK5Vn��2�vy�:��\��r�;�
���s2uJ}NO��m����<}�^�hG�=�
���v�Ȩ��o�����w�~tH�g�����������ԣ��Crm����ή.i�����q9�)-E�����b4����w��H�]h�s}�K�
Mi�r��R������.�d�9p�����吼}�67m �n����Q"��DS�����k�.%��b"�'��1͘�=h.�����O�2�������R6xzQ]�O\Am@<��z4}�����сTt�f`��م�T��h1�\��r4Ac[Kn�<�R��O�Z�`w�1q�1��x��b;�Z���n�����э��Z~�2V�8-%�ZL��q��
�"ھ�M�0\���z��e񴚋*�!FcA\2&��H�$�Ƃ�Ӷ☶U-��JY�L�Gq�
N���H���$��VH3���O��jhBc�h8��%�u�k
S���� ֨]���h�V(Iңd��H����!A$���I-���4ak)$�ix�H �L|$D8�&a��ǖ�L�G�H�W��d|˸f��4�vl�@�H)�H�C.c�R�6�/!�0>�H3�|�H'�������|���ЍTa��j+��y���#�&fe��y#��D�-���Qw]���J�1�aNqM *-xAk@<T�I��G��c��������C�52��0N��j��9�7��_F#x��e������5%�H�����ձjD������"������A
E�����C՝8A�~�.Բ>�/ĸ-Ĥ�{��ɚ]cLJ�EX��e�rZ��a5�L��0��G��W%D�kB�p�E�j�_C:�3��X�>���j�S(���I2�"5�+2���y��
�w����5>�>5��!�%�fR��bkB��Ui$�:@�O`.�qN%.`BG�����$�sA�� �bmgl6%��%8�\�fI�E�d���8����L��eZ��[���I��#�;�b�L�z!���1v8�v6��#1�j>������}�Sȩ�F��XuM1<B�JB*FY�k��Ie8؛"�)���J��Z�Ly��d��AM�����*r��ʰ���Z���Օ��	-�hS���Xf
�\'1�}��F�u;k*j%�]ǟ��H��C�P?>�/hy��[>͢�EH]o-�d:��e_��r��Q�Z�SGTM)���gF]j��RT�����֥,
0M���h�!�f\�e�P�5vS2���D�2k\`Q��������5Y,o).��ѡ�}��^��Ǵ
$3�B���F���L���]D�ꝼ�S̪[_q�}�"m���>��VdD��;]K�����]�Z>�<1���k &�]簖�Q�����UV9�"�����ϘqV�%��k:�,�>>^T�U��l�Q-F�Z�J�e�����8���={!�REO�3HL[��c�E�N|�iS�E������Q�>ު-Gھ8�F�����^҃=*�{�dϓ6��1	�s�ل�vmg~q�:_��q۔c/`�T|R��Db�%֧��H߃��Zb2\���(=�w7�v�ۥ��m82�}�� �4����U�,w�:���i?�/H]���ILi֍=���f�����Q�)��I�A���0��)�6Ԩ����������t2�Um{�
p^���4P=�jԆ�>�M):P�~��ԯQ:��Ԟv��J��FU�z5/���z
KU����d/��?��G��o��?�7;�Cw:��}N�C/����Q)�]iJO�W�^�oT�v&���^Ӓ��޹Vt�$t0�\�.F�E]H�N����f��iت<ոWc�+�6f#��](եŔ�a��
5C��V�pj϶��ߣy�-��^eW�2�r�Ũ����4
X�vk�dDXʏZ|��5[�o*�Rt��v��R�{���S���7��'�Uk��5?��$�u{�Νyz\8�f�?�6�$�V�FZB�0��gu�Z��d�᮵s�n��~���:}��[�e�~윮���S��D�'�)6�������ȼ�ř\ղ��b)/�|�c�*-~
4��C-�!F�~�J�b�v2��%5Z:��%��ؒ[�'� e�'�c��jw� C��'�5�1���-`BP��Z�����Z��s(�`,C��q�/eT��������N�60��W�N�Q[|�d�A����_�����������>�������k~��/��
�;�!��oT�/��9���)�wxU��)��?U�e�v�H��
��?</�3/|E<���3�����/�N��Z<=�[�T����?�S
���vxv����P���5���+����g�_��3�+N|�D<��wK�;
��N���)8��"�����"xz���x��|�)�̇?��'��P��a��x>���a���G�a�(�
#<���xd�M|������9������/g�)�UfG��YT��_Q��y@�/g��!�x�C��3�U�L�?%P`�����O���—�����*�W_T`���E�*�|}A�=
|>��9L�^���R`R����EL4B��\�'j�YQD+R`bg�8��;���"�a���C�G�a�U����@��(�?#��H>���}
l߶U�~
���}�Jܶ��
w+�U�-��r
>[�q�f;�`mr� �5X�l0�@�^�M�*��]
�)Ы@�m���n�v��;���s�-�9
�+��Fp������:�u=�q{��xG�n���U��(���[���Ub�nY��Y���M��I�FnT`�
�Mb��P�cp`�a��&�A�Z;�R�F�k�Z�*K�X�+�T�B�r�)���b�E\��(+5�e�Pj��V���.��B����h�V��(�*��@�|�V���<r��\l�ֶ�s��s��U�A�fLHk���bP ��B��:Q���K�p�P`�8b�e@���s�������?�?Sؿ�O!�?�T~
endstream
endobj

73 0 obj
7148
endobj

74 0 obj
<</Type/FontDescriptor/FontName/IAAAAA+DejaVuSansMono-Oblique
/Flags 69
/FontBBox[-421 -374 745 997]/ItalicAngle -30
/Ascent 0
/Descent 0
/CapHeight 997
/StemV 80
/FontFile2 72 0 R
>>
endobj

75 0 obj
<</Length 292/Filter/FlateDecode>>
stream
x�]��n�0E��
/�E�#�4BJI�X���~��T�e�_�8m�.@gf���Q՜�\�fgт����2߬�è4KR.�p���b����]S���(X��g��+ߜ����^����7U���f�L��YYr	�?�3/�����c�֭��	���R��U�,a1���X�%/�d��Y�K?���zi�q��J�)�F��������s�����#q#C��|
��S�'�U���μ}�\�=/t���x=��'6.n����(+LIi�}G3t��
N��
endstream
endobj

76 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/IAAAAA+DejaVuSansMono-Oblique
/FirstChar 0
/LastChar 15
/Widths[602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602
]
/FontDescriptor 74 0 R
/ToUnicode 75 0 R
>>
endobj

77 0 obj
<</Length 78 0 R/Filter/FlateDecode/Length1 19376>>
stream
x��<`\U���y/-�I��I���6%d���X�@��4�6?&�?�2�&�23o��$D�ZDV�l���*�.�Ri�	����R�����ˢ"������|�)�-��d�����Ϲ�9�f�C+g���pBO�(��1�-Ɣ��8i՞?��g�yB��@�&�bL]�0w�G����v>�q_4�ȽOv�+���Ura������8?u0����u�8�
��q3���݂ò����ЯH�'k8߃s��Ɯ�/��3��W�23ً؏1��+��J��?ӟc�m*cS��k
~�O9�����o�(Qe�e�دq|���`>��'���}�bq�!�R�QB�N��1�Gݏ$<�r��މ�F�6e��=��W)�:��$41��^�R^����6�	�<�.�*�.�R��Ul7>��<�ޢ^�~G��m��)��W��v*k��l�g�Ҧ�R�<�ك$��N�\�	�	v�Pz�6���#�K�e�rb��^V��l�g��;�(�M�Iؤq��]����>��~���2*Re�k<gj�C�9�\gl+�<X��ϋ�l+Z�9ţ(���@�z^a��=�{^Q*��P�5/���������Q<���j|^"!��N�⹲�2�p�s%�9�yȳu��=�z!w�%�+=;ٳʝ�=(1c�(w�[���s�β��&�;i��g?ڣ��q���,��Z�^�Ne��Ei1֨=��`���e3�e픫Qg�+Y
�>�0�A��PS���i�i������Me�=�@?N��Q��nd{X�!	Xt��2M�¼�j��1��r�&�����c��j���zwW��=��nR�h�wkswC���j���&�|n�w]�&�G9����oi�žM8�3\�u�I���F�ز[�ŵU�.l���h^,#�ڡF��0�Ma��1UY�f(S}]��}У�%?u�,V����.�Y���qA����^���W��vL�|�t�2���.|܏v=���V���m�]ذ�j����,_��Ueg*�˗�[,:OYX[��U��ʅ��\�haCYmM��˗��'�r�l��Z�l����]�?��R��.|<��������㻞������n��aD��߿v풫l�ӡ{Ǯ�(�|$�bu8��2���>�/<?E�͸��e�%Uaj�S�����B#���_?����,%�.���o�c�����O����o{G!Y;�z
���ČxSּ�5&�f��8�Af�|F��
�FV�d�*���^�,���k����n��U�4�)��>�)|��8��kx�<���t�}g<�U��;�il��3���)��W�3w9�*6m�sθ��3"GE=	Z:�Eg���Z�=lj�*gLԞ�U_�5vJ�q���ጧ��گ9�i���ig\��\W�+��k�q�;�.g\ͦ��h��M�����b�ҥ�E��X�f�iCOxE n�x\%TF���6"M|�*�҇[��X�N��fl�7��ՓFF�iCĒ"5���E�L豤ӧ'3��x�h*&�o0ҙ��˚��m�ɭ�E�Q3�BdQ��l6ռdIׇ��2�P:lD��є4�kL�$���A��1�o�͑3��(�$�㣩���%Rf:kDD4m&�/m;��<�`C����p^�����-ou���?|��صb�X��"��#FBO_.��X*���D,C>�eĠ�6��@ZO��^��B4���+��Г�"�^C�?���	tF�9Bf
�NᰙH!��"u���̠��$
g ���33ӑ��ᡄ���Y)O4G'�.)��3��4�$	֖i326�L$���������� x����PDJ2��CY&sIi۔Hv(��R�HRkN����J�K̴��������cXK�lJ:�m���A�q�
ѡt�1E���P�V#��+R���`�
��d$&��4sBrz�9l�v�� H�YtC�^�^I"���A=���c5O�^���ĸH���6&T[dGSFTGFM�P��	}O�Gbј4=�����#��6�<�z���i.E�Ll Ib�g�d��a$���<���$I��`z|b�+G������XQ�s�Nڐ_�V2Ґ�/��00�4!���HF4��a���n�yl�d�N��x�$�!�ɰ�f\��#�T
���7䆭;R�^pʠ��z)��Ȩ+DwD%#��Q9	gkx8�f0y�&�I'�".��0��/�P1<�I��P}}AU�
�hģR��X��}=kB}A���`φ@��M4��p������!�A_wh��Y#|ݛź@w�W�7��}}�'(]��?��[;׷���j���	��@W �DC=��
��$�.����Ձ�@h���	���&
>�����;}Aѻ>����GmH�;н&�\�]~T	���n�;B^D
ᢗ���6�/��+�X�҄R"
�� ��:|��bu �
�}]VZ����������n�=�b�U���۲�*���@�W���|�R����)��K�v�?���^k@Ў���5D�h{�D'������p=. ����7v��*��?�$�ߍ�J:��`(/��@��+|�@��Ț`�+�ٳ�"`=�S:�ۑW�H�����؎�m~_'�b�/����_6RY���S#�Q;wz)j�$�!ܞăk���%<Yt��٭pa���k�^J�x٩72l`��Tb��)��H,C'���i�y"�Ǒb�SDP�+�8�e�b�(�^��tQFұ,&��j:�.�N;�i 
H.��`˟62)��b�F|�	a��.#IbI����d�p��-�b��G�,NJ�IpN�1�NGZ��:��u�8�:�� q�u_9I>L�2�1A�Z(X���J­��[�V�ްZ����j%~k%^���Q�J��.8�Z�OV+�#��xQ�T||K�%��1I�r�;�8�r���K��w�ē�8撉ג�;%�8����-��єL|’I�����|���H�}GU���Rq�:�R���HUu�'��ıTG2XKJ���>�u>����8�‡S�SZ;�vA�u�[�h�M�j:l�j�H��ؒf�+�R��%N�Hc��d)6��,�� �2�Ngav�����Y��~�l5�dY��`:K0/�X�p�cq���������8��� $?���\C�iymE�$BK9t�y}�p��6�!�#�N���I#�T��L!L?ҍ!�@|��7�NQɠD&�G&�G����� /�$Y��/gg��X�'�%\�Y�O�2Yԫ�-�OāF�&�3�F]
�M�U����8k���Vr=5>䞴�A�3P:�� �����Ԏ;�3H�1�K��Y�@�0d|H��c�2V�B�
�D�d�p�L���=G�V�}w�~D����ډ�]�9�;�FYZ�Q� [_�k&z�d����Q+���4H{���qI:^�:~��es�c̎g/�e�����rΚ��D�Y'�bN�Dö4whfI���&8�6u����e�c٠�k�^CQ�4��$n���+�8���S�M�,����(��28�\#��b���/9l"WRtj"�!Lخ4� K�֏�Yڵy��p�:�9��
�&#��u��e�V���C�$*mi�Ȇ�"��q��i��e�b{'�Û�s	eA���`ӎ9V-���v-gK��Gt��*D]A��G�8��!JY;�hhq��S���[Zb+B���
��/Jw���\��w�$�9�6��9��HѤ�P�Aq.*X`|&H"|�9
�X��,V���鬓�rsi��ְ��0�4����.�#�E�n"ys�FM%�:��ɨs��ܥͣ$cĉ�8�i:�bK*m)�yqԹ7�N7b�rF�f<�Q�$��JYc��^�9�9T��c��1�>���ɕ�;"L'��|��c"ټ����$��wҔgu�+��J&��y{{N�3H��i!��	�Æ��c18mCQ��g�s���O��,�u�9n��nl��
�s�9�)�ط�N��c�ݖ�]���A����GF�"i�8qs�D�;B7A��^l���ʋ,W�ã=����&�isO�����#�`�RLQD_���c�}(������&ת�9#Y�>��-���ħ�u�L���Y�m�:2H{\X�qg��p������@�q#�%���h�4����7㊤-h.g��iI\?�D<�H�%����݅����;p�W��\�ۙ�Bm~݈��#�,��!\/p-�*@]ɺpD�ήi����K��w;rږui#IY�lE�:i&W����Ȟ>�ٖ��tX���.~����-Q+�{���hG�Bd�)�@zɏR�6—\��-Y��e9.Pirli�!�!Ϲ���ď �C�"����K׍�v� ��d�������CV����gg>�E^i%{I�I�ۈ��,�7�&.�b�L<ϡ���:	���G�@~Ŏ�����ڦiǽ�E�m%�g/D�~'�|d�R-��6��-l��gk��
��v���"Ρ	���΢��|���YC�ˑ|}>�
9`��=y�J��#�Hr�M��]��6��NG¾�5l~�v�����9�|�.�����B5Z\wz�rmq%`g�v�M��+��ߖ�;��]��v�����خ�ݪ�P}ع��NT\�F�>�k�L�*1�4�������;1K��I�:���</�.*в�J���-3�5'����o�)��m.#4�:���oȁ����m���������.U��O��S�w�YX֓M�4s��l"-`��c�^�>I����*HI![sf��$ON���q��]��ݵ}+��xI?hl�������� q��A���A��|�H�B�Å<��D����ĸ����RQ_��a���W�%7��W�|[{+����}��F'����/81}%�^o_��_��g_�p�J�J�ݾ�w����v%�V�.qV�]���qb�K�0�E|kw�8���j��w��[����t�
�uOd���f�I��.]&�u�8�`R]K���������	}�f����ޑx�zG|��Q�����������;r3��7���?��Oq��xv|�1u|�g;��/����p<:4�q�[X������5�߹ZBv���l����~M�Zi5v���&��f�9��h�'��>�ve�(����*PfM9��p�����Yk 89E��|����	�y�;����V��ٴ2�����dz�ѳV�a�H��fr�LϠ�t��m���4�cP*�r�!\���
�S�re��v@�����LS8[�kr�قkr��s*=��rzJ���>٤�f*e��FO���4�ЊBO�rh:,^��W{Ղ�x!g��_i���
^i�?��e�h�,��^xɂ���E��~g����9lQ���v��ïs��_Y���G����������<g��,�����gr��l~r
����ڏ#�6j?���'�gr���k�������k�@<��i�S�?
������H��F���˵�.��|�F��"���ڷk`��nk<Q�?�W{܂��T{l/<�]}���#�ڣ�£-�#���K�h���ͅoZ��߬=���w���o��ݷ��W��;�흮����k{��=��
d�
�Xpw-|}��_���u2��,�]_A:_�����3�~��_wl�/[�E��|т/Xp����6>k��yn��[[�ϡ�>���"�g��3��L>��z.|ʂ[nޫ�b��;/�n�7oWw^ߨ�v��o�M7Y��&؁�;�[�'�>^7�ҍ��c���7�n���V����>l��,�΂k-��x����g�5�o\��k�Ul����n�Y�\��w�`Ԃ��۵�o���m(�9��Az�ӂ���L/$s��A<�[�Ղ���rmpX]F�k��5�ϵp9�sз�j�آTk[j�.��R.��%\|��b.��Es`��r�т
8o9�����ꡯ��҂9�7.��=����tWk=�����s]��Y��Vk�j`m�R[[
�J��A�����Ԁ?m��Z�th��վFmu|H��-L�Z,���J��p~%���
�:x{��fΩ����왰j�lmU#�\Q���
+PW�
mE
�خ._V�-���-�r8k���Y,E�Ko�%��4{���9��6j�f83o���^��\��V�4�é�g�Z���Uh
9X0����s���ysgi�a�����Y0w��90{�:m�6��Lg��S,8��[]jq��j"0�fXP��j�"0��J�>�?�VVA�v�w*rP���j��`�v�WoQO�`�S,(ӸVf��AkQ�@<��0{UhJ5�
P�(�k>����ㇽ���?��ɫ�
endstream
endobj

78 0 obj
6391
endobj

79 0 obj
<</Type/FontDescriptor/FontName/HAAAAA+DejaVuSans-Bold
/Flags 4
/FontBBox[-1069 -415 1974 1175]/ItalicAngle 0
/Ascent 0
/Descent 0
/CapHeight 1175
/StemV 80
/FontFile2 77 0 R
>>
endobj

80 0 obj
<</Length 231/Filter/FlateDecode>>
stream
x�]�Mj�0��>����`��te��,�C�������Fq�}ϴ�.l���ē�;w1�J��X`�.i%�0��h4���M���6�l�-�.��m�|��Rh�ãO�	�B)�	��u����3�JG��d�QV��yn���3�oAW�\���q��!�8�h�2�^.F`��z�J����Ά���y0\k��������}şd�V"NU�P��AB��S�w��o%�o�
endstream
endobj

81 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/HAAAAA+DejaVuSans-Bold
/FirstChar 0
/LastChar 2
/Widths[600 927 415 ]
/FontDescriptor 79 0 R
/ToUnicode 80 0 R
>>
endobj

82 0 obj
<</Length 83 0 R/Filter/FlateDecode/Length1 40060>>
stream
x��y|TE�0\u��}���ݷפӝt��lB@@Y������"�����3n���@řqutF�q�}p5�̃�3���T��,����~����
ͭ:U�nݪ:�N�s��MO��V�E[��ekZ:��!��
BشlC�^q�k�@Hq��Εk���;KR-GHv���M+6�.�!��5�Y�ڲ|۪��.��(_��#�.@:�jMυ7�/PAz<���w,k���w��gIzM˅���2�5侰�eM���oz!
�O���rR��0�������7��Bګ~�0��?-�r�fXN&W(Uj�V�7�F��b��N������@0�Dsrcy�D~A����������jLuMm���?��nDn�}�R�C(}\�>L]���L�����l����
��i8O��h9:�֠�� ��=�Dd��c�����j�.�����
�t�
%PZ�N!#ڌR�'�� ��Do�Vt=S�ƹ�oy��݋/G�P�lt��נƼ���/SO�F/����ta�o���R�\ü�=
;��J]�ޑޝ���)�;��tQz
<5-A��%Ђ-�.�*nbj���mЦyІ��	�2�s�[�Lh&��)�BO����Gc��[���
>�z6=)�4݁�44m��^�c���|�����J�H����h�]�v���^�6z��YF��f氏 7�E��R�]Ц�K�8V�R<��*�0��c��y�!+��9t�o@�aL�C��g����P�_aLY��q</�?�W���M�>�0~�Ș?�,{�<�yꭴ:}{�Ax�y��b��Jt.��U��/'p=�g,洃�TIzbzs����(�r�l-}���B�7�+��<<�*���F��jl��p�ij�zh�#�+<���L;��c���\���)k�/�U*�ޛ�M�&�
�o9��0Ќ:Q7��Ax�s�$���!�~h�9x
��V��8>
�d.ef�l-{=���nMMK�Iݚڟ.MO�b�9Q)��5�AMP��0����3��z�B_b��B<	����%x���x�_�� >����{�K�c��)�,c.gv1�g����,bg���u���.��:�)�s	����-�6qɐ��۔����^3�t���ߤ
R�S�v�~�z+�aZ�>���Q!��	��6����
�����	�p�7��Z�xk�vO����Mx�V��0�[�^܇����_�����}�����Y0�Y}�����2����l�M��l	[�.��le�����}���c8+W���6s/�X�r�-�ݲge/�>�����=����0����v��`X�3�L
�	�=~���_�ۼ�v��T#*_�,���<�X�XB�`nc�ٹ\�բ�o���\�,A��'���9@i�W�=�bv7w#W��F�ᝈ��o�X4���@�C��c��H�2%{Z��ѥ�r����ka��-�����U�\�B���ē`���E��	�f2�䵣]�W��#��9�x���؅g�;�"t)^�Q�V37� ������Ɨc+���7af�X�c��cS�/:]�v��(��3��T�[٧O;s|z�c�A����K�K5�
F���r��903l��ɘ�3p�s���_´�6|+�|3MG�l73ߒ��˖��n� �R"Y��˕�?Au@�+����.'0�{*ݔ������E0:�w�s��.��E�<.�L�����^�1���kq�>
3,u��pZ���|P�"����q;�+���%�6}\�*t#��V�{a�ʁq<Fs!�6X#
Q1*��աq��&���|�K�K�@k�:�w���>X���x,��V�Ր�
+���R��[�5�nA���31w��j�9fӆ�E�/�">�q��,F�a3�����I�o�!7p�R��@����o�9��w?��F�8���!Q��jk��TUV���&��XnN4�����]N��f��MFޠ�i5j�R!�q,�Q�14a��]��EC眓Oҡ�h���W��	���
Kh1atIJ�8���))�ļP�j�BcH�}u|H���ϛ��CMB���R�z
���ѱj�Ћ���6��޸d<T�O�n5���h�Z��^{�s��a
0��1���A�z]����x҂^6�ز�w�y�ǻ���D/nXZڋB�z
qZ5����z�5B�
�!�K<���~-]�.-oY8��mi"�0���{��t'�rSü�#��퍎6�$�o�*��9o�Ȼ65A�,��d�x�50�Sf	�6�ʦy��Jx�@zBz��_k���,Y-��B�B���^�qm�E37�\.�P�r5
�g�z�ݡ���}�}��NQp������3�Oo��n$�:t�B�8���YLZ��+,�%�BЧJ�V���*��k��T�r�H[��a�v~�'���"|H��


|1:�EʑG�o	����½�xo^!E��XG�e��
�L[�� ��C3`l[��$a����"Z
��-��ˤ��݇�d���YB�<��c�C�l��z|I(��'�����o37�Ӌm��vk���Y�)�͟'4n_"��٣R���C�$���0�u3ĸYz�r�Pa�����"�_N�zy�B	TIs�0��_rN&lR��C���S4~Ljf���t�����i���`.�L�=�v��{�m�>!$Lؾd{Kz�Ґ����#���qI����;ܽ�i�N��c�AB k7�`=S�	��~�=�2�,R�e<β�K� y�c�TN���Ɵ��:X3���f*?X��kk�UT0�0ڧ��Ӣ}���M�n�����z�MӛAFџ���2[�,�,Z�F�d�b}���A$(���\(�X��'�͖c�dA8�!�b\������y�hOÓ�I�L&]���5���bl4٫�����B���:�
V
�B�z�C��h��4�����W��C���n)�
�J�^l��+�u.�����J<6��t셳.�J(���
�ץn��$cUZ��^ܸ���±6���rS*�E?q�LZ5+�\���~*���.]3�;D���*��ü�`
������4�~�^Q����z�ɫ��IZ�rqn,��Ox#j�Q��
�z�.M��f��b���>�J�����
�P8|���qc72ǣ��/3��E��-Q���(��F��J�LJ�qBt#�#e�����DGbg�xB�p0���&�ͦ���N��f�`�fg���ܕE�k�𔔚�@LSj�k����~����C[�0�DVZr��聀w��x<޴�'�:?Xk�J:0�ͩg��D���
�ס�u�6R�C� A{I�1$82B�>x�n���O�L�	�|.��}�}�����r����O���&���~f7����>GbrlJ�,�# {�'�Ֆ��^�\��v�m�k�����Ʃ'	�27��p�/ǽi����]��O�gv����c��.�AfA�B_\bJ
:�5�hMM�1Ҡ����)�X��QT��rIEd�����\,�(��c;b�c;cw���b��;c?rH�j�zr�B�5upp��?~���UɁ�t�WQ�e�̬��J܌�5����̩PPn��2٤ٖ�U�)�%��ed���dwe��dDz{~��ނs���;vn�ǿy�
2ƙ;G��	����~��7���<o�\��v��,�=ޜ틮y[!���n-��]��V��.�׮���/[/W^jpT��F�]`�|=?�g'i'���4k�߯�?����VŅ졨6'
�����zTU���eI2�JŸ����8Y�-S+�9|���:�����^�
�k���h���2���Yw?n����E8�oEAA�c�ˉ�~%�t�n��H�S��]=L�B����I�N��Q��e�2�u�\�$x�
hJ�f֔�0�LcՈO�d�S(�����Mv0l�B�J�_^����0hl�K��¸BI[a�旌N&9�\rt��W�����k^�Faӓc�c��/�9r^9F�{���q�/|���[p_�ֲ���m�};�m�(�\���N�wN{�u�n���B.��q`�YgSF�_���@�b�Rk��
+kPi��|P�(e�0*M��FcЁTJ5‚���Y��<osfa!����c5��fl��!�,�`n��	�tЎL�����s�|�&�!�:@�����j�-H�����d�l��}	��y�yO�'ś��6#�ʴrm�6�j]��ռ®�XC@�jT
m����op��Xo������"̃���~f��0�"��P�C~T�����k�Lޏ?���{$Ci0��6���e��(r9�l@)����Eo�N�����|F���fB.�C������L4|�J5
@��פ�WX4&�	��b��YH`�,�ij�	�Z�Ó0��_�㰬��ׄ-(De���)J3,���&5��gS_bӳ���9�����cϤ��ƣ�`c��_����w�q�8�&p3��nx����<*j����͖��c#i�3iu:m֠ǧ`�F�j�5�x��h@%`�\&��*�7`��3rW^h6�
V�hP�,����-�nx��8����S\��O:Γ�������bJ+aJ��Z�5�ቹ��.�}0x_�	|H���ge/+�q�+O�>Sm\.��j�t�$��x��YѬY�W��5뙋��6�����
��0��}>�?��>e��k�F��JF?�:ca�#��n}��S?�����YG�T��wo��]rq���|�@����7<cN�x���t7\���;����E�x�x�C�{��QE�_���7�6��X�t�h�ٵW��r����Aœ�}��C������j��y���x����`{��{�+z��"en�`�I"�` �k���*�a�D�J����||u.R�`P�Ot&�D�Z�͵���
rC�! �l��N���w
(�J��B��p�C~7L��rN��;2��~La]�(�d$��p��C�10����)�Q�H�J�_�2���S�M���|]'�p��>(bN?C�r�er	��h�\*2 3����(��At;���Љ��\=}˖��oW��1��N�!����'VN�ص�ȲM���q�����UjX�Wޝ����a�W�<w��ńk�~H�^���b�:�6�զm�m�k�;�;��ks��v�i5�8G�y���궜��Ai�R	�C.�y�J���d1,�1ث4�>���+�>���)�p�`��``���χ4Z��?���rXr���ud���Ym\X-*l�$�
yj�ޠ3h
'�Fr"��X���M#D���,XC8b�����f�񼼼�.C�D[�!�R�0�rŠޔ���e:��������
�Ǽ]W.�<UCrv�Շ���q�k�K�6;#�Ϋ\�zj[�e�?�L��Zt�ڦ�I��ZGa.N`�b���P��2�1�j
���Ш2E�������13dzT��ӣ����ŞFE�g�BV���%�N|3�n̘ں`��@�|�	�0�n:a���!oM�i��d2�ֈ��Q�2�	�`��F�3�%|	S2!YRR��OIf���0���A��'�hA~��#NJ�
�M��XW@�b�F"V�N/�m���ж���NG�>!'J��-Q&z�%��:2�Q�Ѻ���:�DXJG�q�5CQF��!�Հ��4ɏ�-�2ռ�̻���ܘé�r2M$����L�T��8W����ˏ)��5��e��i�����/�"�.�Å�oH\b&K�!���~��Nޟ�aIx�bD��f���	"ڇYC�H���bD�kƧ��]����|"����J
V��@��E�����!��(�.���8aBc������L���:��oh��-�$3�� Ơ���m2#J�Y�:���s�s����S�¬��Y`͗kU�d����q�l�5�}���7=�� E���y=���t�8�#�I��3B����+��2�ʖ�_�y�t�
�.e�w�I�w�o#:f2;�~�=�s���o��T2�ʟU2�(��}Jv�b��Y�X�\�fw��3������3s�?���%��oe��V��4ŒTJ,,L$����QC�.�c��^�Q��5�G>�DJie1�ԕM(*++.
WW��a|	 *��N��5�W��q'v�3�����/�S�:�&��P�����)���!�L��L ��#S*�r%#��`���^2ip�p������y�ے�� �����!�ԟ%�ѓ�L�;ﺦ%�+Pr��Z._3�u�I:�%	K���i|̷c��WChg�.n�r�g�w+�ε�Z�CnTѧ�~�;�m
4N���n���`J�ꁱ:=��K
(�(9u�[Pp`�a���N��6�D�0�i�Ro�C���d'|S4��E��?��'�/u����z�A�$�N����6b	�#pd��fE��7�6	�b=���b|�Hl��7cY�̉�!���w1�'��Q	L㗑�hA�M1�mX�x�.�q�9���u]8��*JF����FWdjV���s%F��"A�s:g�Nl(q����q�r:�ꬕ1Q�WUN�X��dr��_���Z�jeLݺ�'0�Z+�R�W�OY	W��X�.�;�<����u�����_���+��~���B2P�%��}�����l\?��:M�����D�5����c��S��������,k��,�z�̎TN�Q�y�2���itrv錊�i�|%U4��Z3�U7�L_M,��%1����.7s������7�'ղ
���7���?�yK#�+��0�(�p�hUr�BļEe5�%�̩���{D��:VTc��ڀSc����hI$�*!xyx������<��G����
�?	l�K��$@jS�Y��z�[�ѸT~�vk���	`�4�,#7f$�m�А�Q2�+|�N�����<_a�����u��M�<��٥d2
�~��A�4t����3I��)D�cb�J�w"�.��m�Y�bf3�Y�<�<o���]ӻ��������O�����2����s�����v���kܷyn�=!3���<�>kz��O�|������+��Q���ރp'�$ڃB5��c�����@��,�@���
H�DH��KT"
�R[�l�,�>��}L��!���Ȭ��1>q��i���E�k�������:�
/���:�ܵ��y�u%�����]��/����גѻFo/��By��'��c��@V7�%��T�2��;iw���Om檚ՠ���
hmD���i5��U����+	l�1ߏ���ے����h��j��O��'��)�b�Ղ5��&��~�Ҥ$c5<��P^��>��s��h���!e�9l�Z���Gȑ��,e�G�O���v�]�ߴ�����Bӝ���?����5q=��/<~ы�݌־������- �̃@�b�Q�/3�����W���ͪ��1�Weq���f���j�.F�4���B�g69��m�9�q3S�T>+N�(�)TҮ����V���M��6v	�D/�Y�?"!Wwچ�[jѰy_ZǪ�� p�^,��{M�YA-h���A٥W�ƘW0+�m���cP�!�I�c5O(ȪC:^�Ա�iF��7�F��JNF?�c��=!�b)����e�*��$��ap��c���Z�n���`,����,!���˜ل�:X��X��n�Z�V�U�P���5f�:i�7>fd���jd�*Q'�p��ôT/��~�q@�]�
3��S��)Pv�7r�k�ɭ���֟<�����6�!j�ks�wD��䙷I�G�΁>cc�����^�z�|��j���\p
ͨ�;��9�.+�N�GK,F{bߖ�P����l�p�K�1\��*�ܫb���;�=�+��V����b�<_ܒ��
i-b��}f���4h�r�J�0� �������i��)|���w.8�R���~���ڠ�����k#cuL�Gv��Ay
�%�
X��4��������@������3����$�?lr�"B�p��2���,"6�!���� c�������M�,\QǔedU�d��X�-r�)�+�|9������?z�ڇ�r��7�����at������_��_v����~������޻���cZ�{R�����k��l
֫����Ֆz�X�t.jBm���y�+���������}n>Y����S�ߍ3i�r��N5�o�ڬu�q;�7�1h��W�U�������m�۪��Y��U�3�)�P�H��)u9z�U[�J�C\A�A�eՈ5:�kk�@p��P���-�'Z�jŜ��t�Nc}�	E�C�1k@$�v��Y/6u�p��ؠ`�Qu@�H��t
gv�q��NC�k�s5o�U��\��s��`��b�I�D�{�Տ��U~\!@`I[�Ï쎺�1�PU\�5��r?��5RE�(G�g$T�����@��T�y2�	���@�a���T=��j<�C�|XyA���%�Jg���@PIH��[!�xb�o��h�R�)�٠��`��֟��9���n�eh���2$�2��9�pT�2���F����+gn�vZ��«߲�w/��Yi��MC�=t[ǽ{Λ�z��s��z��{a����9kr*��e5�����h
Z�.�#��������OK&��U5훉�������T����"��*������Y��2��t=�⼮�o�Ϩ�Q��z7睢����N6�^�����}���<T�v&�N���e,^Ӌ��[c�Iɲ�u����ꩆ��'u,�wq
䯎ȣ�+]%	�|�t�bo���:�Gn.���&��0PSr #�-��2��C_���p��O�:��L����ڗ�u��p���M�ՁG�Lyx�%�N
>��5�P�cĖ��o�z۱c������{^�:�J?��g���v����m7����7���w�Š]����9L�`\���2�t�h�����Fe�b�\�W/4_��|u��)�������zrң�d,6g�o�N�Z��A�������P��((�\�.j�
����b�*#P�d�e�IF�u}{�ۓ�}#�2�I�d(''
慂��b!���e4�@� ��b�a2b���L*�̻ݖj��y�,��꼢�x<O�|3|L���k��Jg�0��2A�);!�Z&�9K��5�����u d�C��5r�����j�� .�	OW{������ng����J�FYC�ήHY�g�i�
���`�S9}.���1% <ϤD����[
���Ru$�
�L:���
ә}QAgS|�\����5u�5�+�Zw@�k�d%ϲ�p~%�A|m��X�Ns75�	�\[��*�!�}�~��]���l�i{����-eS�az��V�)��a�eb\�5�^�UZ��α���Z�Y�9���p��+�+�+s/�.��j��~?����u�� s���ڟp>�����{�c���N����gⶸ}�sk�ö#��e�[޷}�?��|o��n�����mP�5�C��a��BX�_hO��0��f���0ߖ���H+'��6�v�X�ʯ��b�R��TGU�IV�n��TrYP+��^o�����A�鸙�م��d��ʱ�E�q��b�%$D]��`'�;�v�e0+XmP���'@���>A6.�	1ġ���9uNu�U-��u�jm@t:��Á�qbP��(��˜bn��)Fr �� p� 0K���\�{?+���9�XTUʐr)Lj������:��Ċ���p�,�2b</,#��ʪR��g��C
4��i��X4��2�Z�Y�S� �t��(6BN��y�28�)��Ib��lv927O}Ln"Gƚ*��ԟ��O`p���J2�e0ׇi���ٟlnn^��켳3��?�mp0W�Tr����
��aG��P�l.1���c�^u�գ12�>!�7�_޿s5��L��\�xO�z�
�2�s�H�`hyk�OP%�+����^`8l������㛘=�^��g����W�T<����K�R�˹�oa,��4�i9��ۂ��t:�*�g,�3�桲d�h^�ɦ&��5�J�)x�R%8��s���ˏ�V������yֳ�f�fN���o��7���-S�#n�ӏ]
O�b�7MC�y��AA�d\�2~cFI.8K$8c��,Qa�]�n[���w��J]�~��d�H{9e��'��ϝظs��߇��.�6~q�g�>I�~"#�����Uoz �[�%�R˹8�5�?7���4z���[�7�ە�kv���#�A|O�A����p�U�o��M��Sd�1�������W*8�����;`T��I^^n�0����g}9��M�\Q�����Z�,Y+ׅ��;"���h-�����6�����)j��*g��g�E���]4u�)��8ku�+�/r��VN�3	"�X\".P$DT(���o��m� _�Q�pg��kV��Yz2G��O��g���|�߮��Xh�����9���g��[P�J�$�J��h�I%���Y�:5V��G�Xs�'��9q��yc޼�g���t?_���7l����-?�y�#̎�����7/~���꼥�_{m��c�Ҿ���Kw�J):�wm�/	��#��O)]$�#�M�:t8�7ĦO��+ccU�,���;��eM��q�^�W�b}�������y鿉��̣�냦5J�DŽ
p�L���D��$��\���y��p��YxR�o��Y� ��H���Q���9�N�S&���n�����9��h,����Z��*�
�L�F�ư�3�?.��(P�C���	AT$Q�$F��8����?��e5���z��h�7������ߋ"9�7��`=D��>D��X�IS����F �� �|!�0X�~򔿞Q��:;	F��/�-m���"N_!9��m�RI�d@���gI��������'_Q�m4��ry�o<o�ݐ�̭�x힆�#��k�0~��]�T�n�=��u�8xc���7�Zr�R'�9��w�Ag�!��O@���T�}bQ���¼x#�E�d�������ؚ�e�e%�.��+�&�����
%{c{J�􌒬K�)Z%�)UA��E����}���:@��
e5#�r����V�=�^"_MW-V=�zM%S��
[Bׇ��zC���k���C\�Y��2�`O��D��n�*�'Hkl>C9<��0\0=������|J�����D1m	�̷%�ӟ�$���.r�(�Lv�N��e�^͔��J�G���2eaG�©���u����7���G���������^�2�"]�O�=.�(����;)o��C<�Qj�M����W_E6�?�\0�C�?$j��pi��|���o��pQ_�U+�)�9�|�<B�(��RA��4��ɮ�2b�tX��'7s��pe��*��c@�\`^m�d��|e���`�]ͻ��uf
�)�<�4��H�UX�ؔ۝�,�<����C��Z�|%LY�h���g�ڝ�CDa�6���qa�)Hp�ʘ"�'����p����ײ��ݏ�,���YN�J��@^���<!�0��{�y�0#-s���B=�;���J|��q��6�vQ;���ش2F�HBpf�`4��\���y���`��E+���E¹JȌ��E0��
��rDS@ �!�'�O��FH�����E3���J:��J+��
�9�
�aC1p���Z�z���<U�P_���KfW:lF�)V���Qg���λ���̯a��k��{�?������֠�i��-�}�~���]s�ó*@j|��� 5���ň��!�"�B{Y�m��@���cq�]iPi_$~ɥ d�3�������x*�s�(�x2	΂|�\�T�B�.G	,�^�I7���U�vZ_�rVg��C���2�t3�c�xRSC��R�T�v>i�aB�4��nO�'�Gqw,#��8���\2zs�fGg�U*�$1������I����m�Zk����Uk7�mԞ��8�ya��;lJ��dg�퍛����q�	����jɵa'��I�V�R
�M:�{��I� �|B��p8 s��`�(GmwT�}>�RU�����6"R�b�QP���
"P�)P��P[<9E$��I������ț̜\1sF?2�-�]��l���S O|rŇx��#J3sFl%�}��d�/�_�X�E��ܪi��[�_QO���h����Q��ڙ��̀o"�7�=V�<����Zc��7�/Xߏ��s�"�y�Eؚc/L�L͙#4G��6�v�E�9��~w�͖&���"+r�u��.'ou���)�����oq���z�
EMF���ƈU�{����)4�9���@H��V6��������+a	D�C��(6D���l�v��s�K���S����I�&pfs?#C��E�	ٻ&����<�2j:���>G���N�Џ�t��o=���V�ho��ŗS�c�˿bu��<�w���|��{��3�b7��]��^�Zi'���n$;Q��=N���W�6���n��iVd65���A��xA8�_����x����;-��	������)t،,z^�T��\]�8���M��j��k�p�#�6�f�2���!yș��1�ŕl�J����3n�d��_���mE�nC4[�6�'�d(�G�*�1��0���8�2�Y�7�J�����!���ھL�i�K��4��ev*�!׼��Rj�3����e0Q1��
�?�b%,ݟ�e �>Ī���r��ڊ��M�l����2�<xS� ���w!FP��g�S������j
�W�HZ��^!�u��6|�~����_K�ao�e�5�2�!�i>�܋l���f3��N��X��Kr��(�����T��E�x8��y���d����J�Eg��~��A�l��$Qd�n�I��JF��#�y�T0@W�_ �!��nQ���|3ʆsڕ�9Ꮧ�������#ģ9���퇸��e
�g}�̮w���wB	�v��f�1�d&!j.f�������d
���T~g�i�y@+I��2l]����r`Q�8qgz�e���ê�w��WOb1ANޜ/�7ĉCi���_���ʼ9�D�b��Ѩ7�v����&���P4�CHC�!�Q��I{�X6�Tx����N��y�,-@�|>�ߏ�D[$Fا�iN��2}M�\>�#;��,/���u�!�>	��ȦΪD  #=-��썡|�"Bُy[H~oe��2R��\E��tˈ�n�3x?�wd��`�R~��:0쌑91�jj�H���U��1�+�!���}J
�G�S/��Q%����(�5fN�r�y$����1����\�Yj�*OPs�q��c�����n���|��C���O�������a�߅��z
/@�������r��k���%��jW-� ~mW��~J��������N���0��>L7�ɖ�T:Oa�?‰���l�H�/�L呁��PA��{E�T�E� 1�@D��
s��Â2u\˺�l�|u�]o~}`��ib���?�����[��BЙl�djw�1�������ߕE*6��t�K\�H#�1���[��F׋��"��H`|���9��Ǐ{�O�VS?^"�����B ��a-�2�Џ<���,����Cz�k����z�g�
 �fe��+D��Wz�~d�a�þ��Z��Q8�� �Y�??��0j��M$�oMM��%�|I��j2��X%�Z���:���PT��pɰ������,;�~�	�ݗ��Ixg"5/nasN�B�R�!洘9>�T�<����R"#Z�O/�g�ZW�T@��Ud��0O�Z�x�����+��x��<�_�߆���`��C�(�dnC&�W<Cr�^~K����N�"o6#
�	r���x%.A��!���Q�q&��f����u�Z��\2��-�K&�IPN�Sɶ�5PƙO?�l��B����@S�gW��}r�T��d�S�F��ad:�\��+R/0�Uᇐ?	��-���EJ�d���g���$��4���B�:�ؑ=����c��C@65�dcCY�qr5bI��X��56��<�-�
:�3�S�4:ͩ�f��ރ�2�zQ��ű��N�]FF��[�[��"��C��|����dL.�-ғ���_���8.��fgP(s�q�hN�T�,.�&������'�O�%� ��S��p�}8	�9=.\ej��q�[�=Q�kʁ"n�ޯ��F�!�C.ΨؙC"��K��6��d|�F�d�z�/0��p��f��s����	��Q0m�/oJ�2;Q[�7;^[�0s�������w��Q�k��o[tCjfm<QS��_C��VXwW����\$��7�M���8�ȸ�IWp	^c�t��4������w�WB�����
%r�[�,Hw���!�C|���J�C��p������$J-�@)S��
�|��\m�Tծ����pu�:o\uCuYuiu���P_YY
���7�J�q����z��tc,�6�V�l�f���
�#s5�����sL�\���&�7)�lȼ��j�K�'��|+2F�nD'�(�h4Ω'��fcU�	A6�{�5��O�L�!�.���	�Q�,��C�X�v����ԟ>�ߞO��[rI��~S�������]S'��%o?b�
���<���y�����gx��V����������4(I(�L�z�Oc�/!&���6{�Qm4�5����1	*<�zL��
7
Ė�IP{��R����'�I��	b�7�����[��gE�$�+2rY�ŶQ�v5(���'�;'0{�eQ�����ߑ:�:BS_�\s_�z(l������؍��ɦ�G�n?�ک�餥�*�BfY���9���w�r�6f�1�6%̞���~�}��h_�I��O'�r�T�E��7h-�mQ�w�*��<��:2�M�'���-��m9̼
<v�H�Rj���s�j;�;Q�V�x%�1�Ӊ<���wY��f�N����|��_*�Ԡw�i{��	
�z,P��;�B�K���T+��w�/��+<_N��de��>�]�{!A��wȟ����{�&��%��}R���3�?�o�߸��/�4'�n��J�n����W䑕�2�z(�k�+�|�%��P~~!���T����֮����hI���Xa4//��Q�:j22��
|w���1��*s;]>���;�ۄL�,��ѯB^�,}�g����~s�YR�ȆzK�5�(
���m�LCy�����t>z�D�K��e������gm[ImN��npܾ���p!�4��:5������w-�9Y����kS!t��gP�B
�4�X�D�b��&��lv��A�r�L0G��Bc��<o�	D�Q�=I��k���L�,�tzvz��(=����J<�NI^F�=C�9S�9[�*7�s������%�E��Vw�6���ԟ�S�h�~�
��~�������0t=N�N��A��$�P�/d
㥥�|�r2&�5n4z����1&�D��`(�,E�p!'h�*b
(��G������ �b"��F�`�73ý������k��=�(��[����y�w�}{��z�X�j����K��@��$���35G4r<�@��Qsſ���0��;�?4>�N"~�d�9�K=:�����ϫ��Q��Ӳ��Α��#�AA��ȟD�dP�AբCI9��:�b����"���C�X�yKz���*������Д�
���f�P2�2����4i�B
��������Y�\ۣ|V�y�	��'�IH@)<-��<ɟ<I�����7�%��
�C���h���(c&�D�d(TК"_	��.�����
B���aY����9�=ڻ��/�s2��m;����t�v�)�����-�ێ��1)\��d�����5�w�n���<({Pu�����*�W0�ȮUn�n3o����)+��U�v_b*��q(�6�GL[�Q�(�4��L}�>k���S���Q�>�/��X�=�xȩ�k>��츛�ټ�v��6����hm�Mv��o���4)c�1�rs���1�0�o4)5r��-w+c�s�U!�:1�4tR؁�#jVA���/D{�m�D�����$�Q������v���8Sg�}Ц���m���79�md��[��6��[� ��?}��hí�H,�O�5��ҿ&�J��$���	)>%�|�4�:�L>��z�3$qK+���3��m�@?&nQy��#��G@W&E)C6�-�0q�꯶��z�����ms�|j��Xq�S_2~��`n�zl����>|�U<!������ƍdfo�:h�/̷�$�����٬���嶶�NK���q����N�M._`_P�ھ��J�mIuI�Ap���^Q,�|d�¤	��"��/�`9&N?��F]c�Qb�K�qEΪ�����S�k[Y�;ikB����=1�3<�@r��xq�8h��=�������yݙ_��8�+2�hBg��)`��:�̬�F;#;�禖������a��l񙯶-Xt΢m�W~��u�O����|ck�ئ�?��	�v=��|�b��hO.l���{�ܽ�`v�����-��z>�Ztp.έ�!��m�G�e�F���:ϔӟ�R�׻~�br�y�]���Lְ��Ysy�d.w�H��A��d�:������/b2��'��X���W2������add?�Al�dkF��tah?,�h��0�}�w�7�C6d_�G�P3���M�~���|����u
D�Oyob�c�O�k�����7�T��oн���#�.��Y�-��x�ͅqo�q��ЄW�O=��7���9��j�μ��;�ݑ��F��7G����w�wZv�wF�s�V~����4v�:͊�������UzY��Z�ϫ�7&�JU�)x�;ϝ���M�����aRd�p����f�>ᠠL(=6g!�
�8`
=��9�XԖU�����b���)C�֯Mj�ӵ��Z��_!��#����x�����Ư�r��4'ׇ	e�&F���#�ۺ��W��Mͨ�l*m��ib1	'L���G�,��8���)��šh>Fþq��o�'GF�Wa�h��́�
	�F	�����|�+.�q_� U�ñ��k�ߴ1�?xޅuMw�H�A�@���n_��c��K��yyȳ�b���m笮/��A��/�{?z[�Or�9�h�IO�W'+�Z
���z�4Y�V���)����>kvƕK3��iO9�x������c-�f�?�s��*
QL>�n:h�N��>�6t������;[G�bn8CO<A���1�ѳ'���qz.��l
��q�Je�N[��T�$���
�B�6�6�-�6�}�A���q�~I���E�-�Neר���x��ԡ�~�'���SI�o��xdߓr�rp������ �aaO2ȳ'�F���Gc����?�E��U�K��i '��9;�yT�g��
%������‡��(q\
% �; ��}ť� Ŷ�DN�JVeÂ��L��wީ�Q����y����ڂ�ӟ����b><%�,z��"n�RFQ�6G���Sj颐���X�ZF|�Du��eՁZ�.z����_T�k
�2����S�/Q�;���:p�#��U=Y?�!�!g����`����Z=#7�&��[x�C��J�(WqN4h
�!3.����2�zB|��|yrȟh�Cj�'�uxȯ`y��4u�k�"�}��#A�T�H������޳�螮'K���^z��*�è�甼��-ew�]��_���.	0�w�,��������G}fܒ���]c�%�����]�ݶ_�g��E���FE�*��4�>$7�6�D��h�N��VWf����@]��s�m
#>ذsĞ�QXMvq��2�C(F�����=O����t��~��~3�l)γ�E
by��eU��Hm��t�euH�ŒC�r3�L��y�����G�/U���)]^]�ײ7$��B(����{���!i?y)Ƞ$yX�G��/�����JKJ���e���h�I�K5�c���)j�mCǨQ�?1[�Ţ�`"���BY�����l2(dA Ř��YK�����DIu~~"�h�MF��ƌ�B����	�);�����:K��2Bia�R��8y+�����TmQ1�JP@|7�*g�|'ڒ9�1������; ��S.*��~��^����������"�������Llϧq�%W:�ل��~��V=�����W�,/�/���
=_SC�~� "�E!.ӥ�oG~�J@�R���G���K�a<�5�u���Sb%?9Ⓞ���8]+t�0Ӓ��w��ݹ�Inu�gxCj���'2'QM�ԗ���ݺn�-�!;���+�q{%F�ߖ�DŽ'�'G*��|s�ʛ�]e�T�Wv�!�a���-���3�������t�H�;h!��F���!��J�&�kd��ˁd!r���h�ُ�S�_�?Z[�����V�-��:Qm�e=�*�5&y됇��	���D&�n3'���OC�l�Tf�y�I:�zIFC�g��=�e����"�!�eV�ˀ[8��~�e�ATټ�U���?c�9:��=����f�ƚ{.��������-���Ǜ}.��u�n�d�	ި1:�n���W�2{K.��'a�p���r�,�u��]_SjQ����9G:����0���w�u�-6�|�T)��g�'r^��_k!��@2@H%�-���#��F��a�U�ߌ
�!��G�
�]��BV��Zj�7�Jt#ܻ�j��%n�;�h�丟`z-�;{�24���Eoa5:��b3jE'�,�ݍnŸ�Uh3h[sᩏ�JE��5�?���^ľ��%[#�@Q��I�����`�\����u��z�7f�{��L���-�X�=h���Χ]���]�-އ}�}��g��*4
��_V��k�-�?E�r�E9��S���~��]��D2���;�ԣ����?W�U���.���j�7��F�����a:�6�b�Szl�`��A	�
_"�2��%X�<�!	V�����DQ�]�U0��Ռ�yT�5��{E��h��R�u���$X�jg�z��Q	�H�˗`)t�̢|]�sP�]�eH��(�r��]!�
4Kw�+�YwR�UP�����L�5��`��n%���c�~"�zT`zZ�92�Z���2����r������SXI�Z
���S%pd�"��#K��,8��$��#�q	Y�.��#�Y�G�C8�f����K0���`���J	9>�`���n
�I���g5�/���Z�/�)��p��<鋐��`��黅��Na+�g�m4�
;�)�e2m��27S�O�S8L�?B�<
�p>�7%m�g��&����(�����6�N�
+Pp�V$��
���SQZW�TJ@
����-��FK���4���?�)9�2�U�*�
y� μ�U���`*��c�v�g�3+�
=���P_7\]h��i�C���	h�i������:��c~�1��.�?ۓbhI%�ʅZڠ�]p��P[�G�9�Gj]:Sv�
�k����t�ɨ.��ڋ ����#�qi����6� M�,�9��4i�Z�ɴ�zq�38�Z�;�e��9��H�Lj��z��N�Ok"]+����P[�֍�=Ҙ��
�/B9�%	��#��T[-���i#�
�}�����-4o��\9���o t�J۽L2��ˎ�@kͶ��h�T���v��,��(>��'=X34�tD���p������݄���hŊ��3���#�l-����BBK�Y�C���#�AG����c�Ek�4�M��Cے�e���f��C�n��Gf9�ZO��{kiY:-��%o�#	��_��1ʴ���u
� ��@�I{�L�����b���Ա���`��wߵ�RJ�l눷LC�a�LZ��:���!�|cz���|�3gAHhi"p�F�w%I�l�Cjz�Y�F���,������Nʥ:���i�o�{�w{m�]O�(;�6�Q;��x�^��>���l{2t���ϴ���vJ�t5h�y+i-�C�Ah�Iz�*�����vd�T��|d��:ÏZ�h�Z�E����/�j��.����_�cײQ��޷\ⷄ��9�i�R	3k��C9�W�G*�wΦ����6�Y7й����vi��im=?���?���ݴ�Mg�"���+I�Ӵ�uґm��pٿ�sA�ŵ�+����{�j���t�_d�I�� 1T�k�f���?�i���������{���%;�U��Х��n��L2�I�d�'Ԑ�̬��#K�g�п��0}L�}?sd�I�� ��֝���:�E��Ht�1��5��uе`��Vl�|w�>��`?[_fN���A�����w63���A�=?8��k9c�W��Z;<�g�a�$c,�R#[��{z`���0�?�#��5+A��R��R��{��U���4d�L�B�[D��o�@%p���QH��"���ֺ���1{/y��
���7u��hY�*<(�^�*L�X��YBCGWgGWKO[�Z��}Y�0����(�$�	�:�ד�na�Zx����0��al{�0�m媞nafkwk׆��
��Z��i�g��\��ҕ�|̈[c6�vu��T�Sۖuutw�艍(s��"R6�Θ5u��zH��ղ�uMK�BNJ���ue[wOkW�r�m�����������@U�CB�;Vv�t��tN�Ɩ��”֞��֮��m+���-�B�@�n�j�
:�+:��I�&�l�7B��VayW�Ƶ��M���]m-k�	]0�+�S��Y��ˠ	�>�AKjo[��.�h�^��ֳl����?!�!
�X�J������вv���޲�V����c����lN7���!��T���lx�����=�%]�0X=�	��e)A���Ɣ��Ӻl�Zژ��֯i]�CǴ`UOO�dr�ƍk��+Xֱ&��gM{rM�ږ5��5݋�e�cm��r��|jck;��G�M�=i¤���'M�&L� �;��qڬFa�ę��S��֩u�٫ںi�(2�����	x�Dh��K�������`hS�z�䲎
�J֯]cDꁱZ�M*i�ۖ����-+�Z[�`M�ت�
�B�RBRd�G5�P5�Q����u	�ۺ�후]k��H��X�J�l����-��j[����fԏ�PNw�Q@;CC1�p!�
-��[��C���[{F>] �Y����M;O{}�&	M���ٺ�mP�Y=`����]I�mY�����I�	��E���sf���ִ�d(��#�֝!-J�4��N����mݫ�{���p�i�$@�U����
�����b�s-k7	�ַv���9ҵV�A��nZ�{U����0+6��n�4pv�I9�dk��H��>B��=-�z�qL:�"�z�WK�<��2�K[���3��3k��/�V�VĄ�������B�j��,,**-����B�(/�*�ҩd����HRI�yt���AU"a��������E+{o]���B����>�)�(\������1��ǘ�cڐR�c��i�1��ǘ�c��i�1��ǘ�c����i���a�����{��L�(}(#c�p���G�9W�M�&r�V�z��?V�4:g���~��?g�?��Ò�J��q�����a��S"�C4�F����-$��hܧ*��d�A�p=�kpqh1����!��������GP/\���:\$�0���Ðsr��~��'����~x����p�Wc]�~���ao`w�ԽH�K�N�� �^��ew�U�
cU���+��
�펾�ӋQ�����9��C����Zu��h�Ъ� �P�n��
��!7�ߍ0�*����;�6)��j��=�/?;O�������]�΁����`d'
�p:
7ӻ�)�A�
�S�^�I��ih !;��S�Ϟ�N���E �iOc'�x*;���B��)P��dvMO��x�ρ4�'�����vBz1�c�}$<�a<�i<��	���Ӝ�n��5�XZ�������XxB�:D�#"��W�:���B�ZE����J���j`�j��@O
��)���%�5�%pɠ�<��v%�
	6���s
�@,H��ف|��}>�8V�@3�ZW'\[�}2�a�ʑ�I��õ��p�
�cp)Q}推a�zv:3�债c�kj�i\R��=�L�u�v�1��.��&Ǡ�ٔ.H'��5���E<##:����RrZ�+��p�@D9P��22����ZHn.��B*�Ʌ���{BL� �g����ҽ %� %� ���&!���B?�g�v��1��0��ႛ̵0��¸]K(�!�8	w�;�z.{~1���/~A��'�0��{��o'���ߵ�~;���G��Ⲏ��e;��.{��h����%�Q�l6`�&��5�g8���?i�
�h(��.��N.Խ�Pw�B��u��-�MX�K.��㥢=�{/��>�;?�+���⺒�.׍5�&<Vȧi8���4�Ћ����I�q,%P<�9���Q���}�+�J�.Ϥd�j����0�ҟ��D3Q8�5�9�a��q1�xI�X!*��|E�"GR��I�+�J�R�T*�JN�(��B�\x�xnZ�<��	9
�	�؉�d�d�kf�0Sf��Sz�Y��,z���������B�p�i
�2{���">�_���[�ҫ��`�>��k�T/su?F����4ɺ��kj�wa���Z�75�g�����6!ۆzG���X5a�K�p�aZ�ȓ��%��[�̚�������io��Y��y��J��q�!��DM���0��3I�z����rH���P�D�H9$�Q��T�re��h9ߨr�j����2��L��2+G�YIˬ�ʰ�2�e'P��	(N�U��o���`���:�>8>�B��[�.jl
5.	5�µ�wdžU��-K�j�o�[B/]�t�*����B��{B�}�/:�~�E�����}�����]$���,Nn��o�?�%�Q�ۖ}ݾ�����T�G�5����=����GȻ&��(�Y*Ѹ����x?�Q/q�����:J��ǥ��¿D�xS�64�W��?6,�����C�A�帴:�>�)��!���m��w�������{u/�&1��ݳ.z�t�r�w���o~�Ƅ7��ʣ��̉������C��ʇ��P3�u�������\P]�zL� �M7��P
"��T��4��
endstream
endobj

83 0 obj
23539
endobj

84 0 obj
<</Type/FontDescriptor/FontName/JAAAAA+CourierNewPSMT
/Flags 5
/FontBBox[-21 -679 636 1020]/ItalicAngle 0
/Ascent 0
/Descent 0
/CapHeight 1020
/StemV 80
/FontFile2 82 0 R
>>
endobj

85 0 obj
<</Length 493/Filter/FlateDecode>>
stream
x�]�͎�0�}�"��b���$���Ģ?*����J����s��J]�N_���f����ws�m�c��s׷S�
��	�)\�>q��]3�'�n���dK��q���П��*ɾ/�n��H�6�p
����Ԇ��/�ӏ�qy>���W��~N�d�N�p^��\�_�kȬ���.��������C*��Hi�6�ƺ	S�_B���u����I����U’ӹ�YO�T�L�s��^�X.ޑ�r���=ri��"W�{d�,�/������;�7�W�-���β�������Dv9�avя��U�Le�����W��+̎~��:�=�~����~�g���~�����K�� �W����K��#�{8��������P�W�_qB��:��S�W��D?�(�{�E�W��J�����k�?؋ү�(�b��X_�{T�K���_����`��VK��x�o��p74��Z#���@��i���O��f���_謮{FT��7����
endstream
endobj

86 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/JAAAAA+CourierNewPSMT
/FirstChar 0
/LastChar 62
/Widths[600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600
600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600
600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600
600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ]
/FontDescriptor 84 0 R
/ToUnicode 85 0 R
>>
endobj

87 0 obj
<</Length 88 0 R/Filter/FlateDecode/Length1 16932>>
stream
x��{xTչ�Z{�=�Lf&�a'1\C$��$��Hn$� �̄33qfF�b�� Z4���(�j)F����Q�m+��b#��ZL��[k�I&�j�����̞����wy������`���zD����n{�O�A���5��1ڮ��#���������DH��S+[;�N|��/ M�������Jz4��R���d�_����nja>���F��+��0���>�mm��K0?
s���y���[�0������B��O�~[�۶��z��CH;
�0���C
�D�4Z��`4Řc-V[\|BbRrJ��c�����נ�կnt���້�l�D�������'�=�y�E�p݀��
�Wx:����b:�nC����'�����F��`�	."�������=CR�a���Zr�,�c�=���kAf�)��P��O��h����Q�L�
��o��]D��R?���>��]N���B�n��.������(�J��d�z,@�=*�J3<�W�+�Ah��[��+n{�x�P�ކ�kQ=���J>��Lq
9��	��@��I�W��i3�6M�W��Zf��F\�������|�t��Qn1B�Z�J���`�Q~ݦ\5���? P<W,'�Ý�bz��  � =��J[�7��)�V��9�@������2� eh:�#]@��iס��9���j$�e˖�B�˳�>��ʒ�)�#��E+�G5�c:��Y,����F�'Y��bV��v���y5��n��,S�:W��b�b�,ú���cR�KY��Z�_nl��ܛY|��[<|�L��f�q�^Z4�$b0ip�A��6"��9�7YN���ˋ��[�ҭ��"��Q��]Z�j&�<!�0}[\
hhP�E{�n�5H;1Y̊ϵ$��-��7v¶��-q��m��4���F�-!�fT�4A6�iI�D�g9�4�/)�V���܅�(�����/X.�|���Vd-�ڒ�S������kǍ��qB|b\&����p�5��M/,H�I,ZӀ@���h�ms��7���9���ko����{�<V���ο ��*�,[y
_l[����<Eʙx��6�`�����g)-���sE:��]�~�g�螯>�B�Qʴ�i:m��tض3Yo�-#���-����.�Y.��
(]�?�Y�o�Z���j�	͝��߹���������/_&�;�N���s�Q��==K��S���V�w��aЌ���������шHc�Л�{��� �Z��'��	��
���7.y���A�ǿ�]w|���G�?�{��e�O=pα��"S��tT#I�k�
4Ϡ���������s��4��mM�	�p���}�~�g���nqE�m�D(=���rt�P�jO6K�XrY�Q�A�Ψ��Xl�x��?�'_��⬞�|n
�cf�Ru]����ٓ�h/�,���6�����{O+���������49��P"��-���ăX��_J�;�sF[��m�����qW���B�r���<���xsz�g��jA�6m���h�������#��c7�/�,���ϻ�6o|�",_�y��E�N���p6a;���=O��Y���bB���6lc�YܝbC����y�hK���Y���mJF0��ǍW^����
���U/�5�X���z���{u��L	�e����3�����?=kZ�X�0}6�o��D����d�Q@�E���4"��/����I:�_xQ������X���`�eOOIlSw�N�Ab~nzƲC�Ev��JI3�iq���4K_7������ˊ��$0sXr0�����b����9ڃ�x��j�����_.�N|�Z;�����;���tѓ���U�;6?����1Wv��>Z�,h���@����Z�*N�ZQ���ǒ�nVD_�Y�E|�}�d<��1^f�$$k'
�3����J�.ܮ5$k�ቚr��,�+q�F�-�K���
k�Ȋ/�}�����e��ƕ��_�n��٠�4���UY�#y�oN�M�N�PG�W���}֤"���P�>P�T�e��"a�	S�ܱp�m鱦׊�K��j�W�,f���M�e)3g͚�rS+��������Y\<�����h Oƣv�=�$��Ic�tzAkHJ�V2&-�`L+&�-���%�Hr�U��:l�9a��8v�U�Ҙ]ZM|�sDh}�%P$�,��˥j9�ؚ?����$sdz:���pfP!7���\��yp�F��ukoz��{���Uwp���o�������ym�^��@N���y7d�S]��Pf�����%�
���|�?�y�>L��`�jB�}���S;�����9:�j3�I�r$��J���8�/�eY3�	,�Z>_;.3R������9�ɟ^kډ��i����{��M[^���-�/�O�_請�w�|�{��3ʙ�q�Ă��a�ea$J��%�Z�h�$I�g�>8�@(*b(AD��'���^����D/�����x,C����Lk�>�*Q#�g�Z�<Հb�{چD���HL�^��ݍ�XPc�΋@:��{�>��K��S��K�����<}e2�Hײx:���\{�iK�ڒr$��X:�����8�	i�S!R�#%��"�*�@Ev��u��ki?�gaq��*��e?}��S+vAI����=cR�K���<yv�u׍�G&?�'"�}�A�ReSr�L�v�ҷ�/�鼆��18YL14�2Y�$\7	<���WJBϹ����,�EJ����'��e�F��na�a�qO���ɻSv���Ei^�JOR㙸pX�N���ُ���և���=7�������߽}���-�r|�8Y(�������+�����=�����cڵ������oWr���(�5eۓ��e8㬇MG
P��
1z��<�E4h�^Q�њiUx0��Qϭ���-��S���I���
���=���M�'V4��1����_��;bɎ��؝�(�4M�o+L�^Ji| q���M�vnڴsצ�?��y����y�©��Y�M��S���N�����x^OףH�����w�51[o����F�W����
T�뾥��>���'o}�	�3��+t|��	�笒����A���F�=u�n�4Ə^1�@�P��|&�o�h�Aa�Չ8��diw7+�?}ͻ��n޸q˖�7�SB�?���-���`+����9�����0}���OA͈}V�g@ M��%����"&�����l%k�^CĊF��!%_�N�7���ƀ���{6��‚�"��"�Vj��R
�6��'��I��Z�u�-�U���?S���x�e�yl���<pߎ����{i3�xl��=R�o�z�d��w���%Cb�yjO���h�n��3��S�$
�={�}<��XK�~�����}A���5R�>Z�o��}j��k��Y�{�f�~3��A�z-�7MզY�l��_m;���iV˸�Lk/F���^�
�������@��S{��s�/�\#���z�]�{<�h!�쀡	m�g�"h	 �^p��5 :�A�P��fK�F�5hP^��H�ڇ��3_q���n���`�0Zf�F��I8�$��І�q���i��L��Лc��6�e�=��V�	N[�͠��c��;�����ŕ�����Hܕ��а�S��D{<�V�a}�5����S�I���`��U�F���9�ˊ%{$a���(�Ct�	:�t�W���.�8����}�>�`��N�3�/=4j�6K��H?� �/"���i,1�$8���z�V$$��䢙�<�s���L��f�g�'�9�;]`�Έ�Dc�4O �q���ۄi���~C�����T]:�ѓuY�Ba��D���B��^���	x��%U�S����{�����!���6�#I��=�K����t5�=b�5qZ8�51���OH���s<�'�$c��ra:���+�]��n�����5�;�l�֟KNm��~Z��]��~Ր��7)�K#Sѵ�E�s}yq,��=!���H�Wz���z�=[��F�&���3Vߙ�3��GR��6'٤ѤFuQ��0�g���'�!D�6+}�恏�iz�O�Oxv�tw�j�$�V����?��궲�f0^vl��ϊ��\k$�Jv��j!���f9ݣ�P�^g�x�=˂,�b���ek�ض�Y�ȎK-vk
��5��mVڐ��1I�0�v�S��{qC��i�#g�{��-��`͝�(�6C�y��b{���d��2`0
zS�k�
�,I�ľ��sLl��Sb��Af}����|4�j����Ek��\fgkJx0+�E�����f����Ͱ��N���:�ΖbJ�g;�겺lKb���hx���Y����,͙Ә�s�M���4�V�x�1���"����j�����AҪ��t�hS�����)��Q��Ķ%.Qߙ��K��J�=6���)Hc������NR�I	�u��`Yz�sa�����	fQiR!��M�m�|���T�k�]����}=�~��ڕ�-�|�ݓ'�?C�O�G�:���g�n��p1�b.^���g[ ��BO��r�)?G�{�M��7����Tv�
>�^�|��5�+N��s#=K�����Tްo��㋟tN���p{|�8��l;}���o�g�s����z?�w�~��-��&~�q�б�wϔ��7�κ������.�t�Џ���S��0Ёϕ���蘨_��_ֱx
5�_��A��3hZ��&�~{ގz�Nغ>��Y}�q�\gP.��1�O/An7Ý-4����+�w�7�0I�Cx�X���Mq�x��7i��J�#}���|GӭM��hk�o�̺I���y}��A���k�����S�؂v�eHZ��P
EXK��A{n�
���X��:���Ա�
�X�>`�:� 3��:f�Oձ�$�q�~;�@�ѵ?p�"���a�:�H6�P��׫c�ձ�'�1Tw�+�X�F?R�:�a�W�FTlJS�1q�L�ձ5��Ni��#ز�9,Oh�(����
rIK8zݾl��ȏ��r-�
ɵސ7����1�yW��ˍ�n�JoHv�r�_nkohmi�=�����s�Cre�(	n�6r����r~N�t��E���"aP�9n+��������P�=��m
Wzs��p9'cj1�M�'��^���X31G���1�6�rnY�<�a�7���>���-���=^�;x�h��`��}-!� P7{�^��2�����l�)��60`ʖ�����s�h��-�� ��f��f�����1�krFn����38$��Gv�B��7��}^�f�4���G�A�4����&Ao[0�io�r6�0���=��:ې
^jlm�0Mִ���aP�ע
b�AJ`�zfN���r��C��Q2����@Py�@����͔�m�
��9���憦��z�FO@��P{�*oc��(�BH2�~O�#Tl0��-wC`��[�DW`0��0�!��2��
E�rO5������A�fg�q�}����f��6o��(J
��sw0���������5�`��x��
t,��A���<�P�J?WcekG[s�mb�n&!�#�Oh�$%�<
`��(#���"�q��r˰P��^�O�
BL�H�x!kAOH���&;rC�`���a�T�9���lb\��̈Ձ�Aż��!kdw[������n(���iv��fw8z��qqC���U��u%C��<
����c�r˭��@�D�܍��W�a����`���k�((Z�����)5�)�WW��u�����N�U'��V/t�9��G�3��E�����e��uT�/���eG�y���,[v.��u���յ������5WUił2W���UU���JW=0���[UV.gcV�-�SG���U�$[.w�W1����!�8j�]�*�r͂ښ�:'�(�U���Z��t�����fI�k���l�T��r}���Y騝��4��keN�Zٹ�m��먨�K\�u��NG%�e�̩��d-�*sԻ���'��(�p*��)�We�\�t�q�
	ad�9Cp�
s�U�ZGE�\W�,u���u��sJ�����VW�9�/������ur`��J�f��*0�񩯮�Te��Ι-;j]uL���jP��v0��yU���Gl���Tl�j`��Q�_���r���m��V�[)���*�3�G�R ���!q�5>�x���'�Rᆒ���j�e��N#��zV{�
�X)���b��%�3�A_@=�B�V���^�[a[hP��	9ۂ-�eM�%�Dv��j��v�(�G�H������68�ZV{[;r�6��3�I��-�j:��1\��ay%g�á)ˑ
�د�i��%�j�m9m�m�j�D�Љ��D-h%<1���&�Fx&�Q>��y�F
@!��	C�j/r#ʆU�}���2���3/|{a�j�z�Ҁ�`�
8,��v7��{�|��󗁋�m@�|[�N������F��\�J��ç>t˷�}���\�H
p����4}ؾȮ��l�
"a=�P�+���\�L�_
�9@�� ���{����=�Q�"hE��u/�{�^�I/`@k������'�O
W�� �Q��_�:��o�����H�:�C6��(�������Q����oӅYV���8��Tx7�{^ծ�\��G���i�w���+є��
p
�|�犄p
�n�Q��Ҩ"��Z�q7P5�iS�G80jEw%��<k�Έ���9��ÿC\�F��V�Sb���ǹ���>M0jU�x �CX�3�ÐJ�3�C���6�@J;�sH� �c���݈�.![ͥFЬ�sQ0Y�c���|XE��ע-���JE�v�av�w������P��`w�?�#{��\^wd�Y��w���p����m�#:<"�,Z����K"���k�_��%�ïLF6�fH��F�O����V�JF<��e{��-���<;��]n���a�ѵh��Wv^��l
����b�5 z��mv��j�ۑXS�P*����g����ǿ��ǿ�0X���-�jQ�0��i/äcPϾ�ˑ��t�UOYQ4e�z�|u��IQ�j.n�/b��k���Bc%�1k�յ`T
u��Qb7"c$>�o�)��y�E����j|�&����j:f�~o��Z����
�����񍬄#3�7#O�Z��<��[���3�r.f�=r����QѦ�Nňs���} J�v5"�X
w[�����q���o�s�����E�oΘf^�e�Ru�����Xw���s��_
U9
�h�ws6īg��ʺHF��u�	�;�sl�}\W�S�E?�vd����b�s��	��b� Rs��˩FU0cr�aV�A?Y��`M�~��,�Y��q�8�v?�g�"3��h��+�Vo���l�W/�׉sN�V�)k9�JX��o�J�v������ĺQE^����1]M�a}H�p�\\bD�J�����]�vq~L�l�W
�Y�j��1Όg)hT�glu|�]���mV���6��}�'�@�Q)|׀lF1���Z0I�*e6���S��3�����Y��e6⒣b����_8(���_o��_+��7����9�C�`-��98�\B	��PdxVR�Fy������4/����Z�6�;W����9�>'G��S��N�w
�(��ⶖ��*<��Wb�"
�Rn#��|��Tc���n��!L�!+8�kifCޯR�[:��je_Ge�E'�rp_�
�P��R�|AT�E��@���A͆�ɣݿR;^��=X��Bհn�o��.'�k��y'<X�������PW�fG���N@��s8�o�ЪR��3k�'�����yJVz���7�}(�[y6��~=�OWz��`W�����d
�;t�+O�>N���r���#y)���wLZ�*h~�	5�	������5|V;f_�J��o�T�T�m>���m�����g��0�'sT�Ay>„!��������c܊��>�a�2Js��q�2&��o�����>�\G��rx�k�;J必@_���~���s�z��̃�$�h�����z���Q��
��j�c�Ƣ]p5�q�3�#9�pZ3ʂ�������9����c
���X�넯|ۗPB)XG�)���+�������;��)���x���r'��^�tq�ti	�d/�#�[���+�o���R�WJ��O.ēϺH��GI_�W��_��C>=�>�"�=�O�|��Q�'��q�%�n!S��C��G)��+��.�[J~Cɇ$HR�A9�E�/Az������Ȼ��;Ť&���4%o�e�ަ�-9Eɛ����*�M~�Hޠ��.rbK�t���(yuy��_Q�2%�w�H=���(%/Qr��'/���_�S���I�<D~�^|�P���2�]<�E���.ҽ�!=K�A�:x��x������L���R�4���R�%?��}�<��Yz2�<a&���*����J~�������Sȏ(�C�c���a���C~��������<J�# �JvŐ��H;)y8���;�H�C��.J��z�yh����Y҃�ȃvq;%ߣ��?p�ܟE���>���x��H:a��C�h[�ȽVr%�)�D����ݔl���C�J�k-��[G�d�m��ﬓ��;�Ⱥ4r%k��vJ�P�����Ij�%���ψa	C6��AJn������N
t�o��#�	���[��*JZ�I���i��K���Ɔ4���d�҈����L��Fi��,�^!7���x��H �ǓE�,�d��iA>�����ZJ�#5�TǓ*J*�����Cd�r�+Y�a:q��$W2��L��R2fs<�f凈3���B�tRZb�Jm��[���b�#V*���n��a7K�X���G`f��$���ލ���z�^��D���v�G���٠��+d%3'�bJ��"�15U�1�L�dڔxi%��ȵy�ҵ�H|P����L��SSI^*ɅQn2��'J9�Ȕ�8iJ<��-0����G���]��IY�dJ&�,2Q(�&R2��񔌋%Y�%R��\K2)Ɉ��2(I��H��<���G�@r%c(
؎�dxeT
I�$��dJ��CR9IL�"%���x��0��[H����Qb˭%�,VbQ��5���X�`g�1Hf1+��v1�Mzbb�5]4RbK����B��h���)�0�\!,��x
A���g�V<���O+�o�Ơ�����
endstream
endobj

88 0 obj
9424
endobj

89 0 obj
<</Type/FontDescriptor/FontName/FAAAAA+DejaVuSansMono
/Flags 5
/FontBBox[-558 -374 716 1028]/ItalicAngle 0
/Ascent 0
/Descent 0
/CapHeight 1028
/StemV 80
/FontFile2 87 0 R
>>
endobj

90 0 obj
<</Length 383/Filter/FlateDecode>>
stream
x�]��n�0��<E�ݡ��!�B�h�8�G��L�4
���/��&�P�%����ü<����W7��E����4�]
�
��R����uEߺ�� ���e��/m;�i���iv����
A��p����G~���}��;�(�2�@��<U�s�CHY۲��ݼl}�_��2�P���R
LcU���
�4�2�E�m����\���r>T��(R:�#��)�5s�3�
qB�	���{�?#�&�9����br�rO��C>3�O��ҳ��.���oh��
֔��^��	֗�?:K��2�k�aM1�O�쯨>�������d���7���R����T�?�G������==��r��8{?##�s~\h@iNpB:�3<#f���o��
endstream
endobj

91 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/FAAAAA+DejaVuSansMono
/FirstChar 0
/LastChar 36
/Widths[602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602
602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602
602 602 602 602 602 ]
/FontDescriptor 89 0 R
/ToUnicode 90 0 R
>>
endobj

92 0 obj
<</F1 71 0 R/F2 66 0 R/F3 61 0 R/F4 56 0 R/F5 91 0 R/F6 51 0 R/F7 81 0 R/F8 76 0 R
/F9 86 0 R
>>
endobj

93 0 obj
<</Font 92 0 R
/XObject<</Im4 4 0 R>>
/ProcSet[/PDF/Text/ImageC/ImageI/ImageB]
>>
endobj

1 0 obj
<</Type/Page/Parent 46 0 R/Resources 93 0 R/MediaBox[0 0 595.303937007874 841.889763779528]/Annots[
23 0 R 45 0 R ]
/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 2 0 R>>
endobj

5 0 obj
<</Type/Page/Parent 46 0 R/Resources 93 0 R/MediaBox[0 0 595.303937007874 841.889763779528]/Annots[
44 0 R ]
/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 6 0 R>>
endobj

8 0 obj
<</Type/Page/Parent 46 0 R/Resources 93 0 R/MediaBox[0 0 595.303937007874 841.889763779528]/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 9 0 R>>
endobj

11 0 obj
<</Type/Page/Parent 46 0 R/Resources 93 0 R/MediaBox[0 0 595.303937007874 841.889763779528]/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 12 0 R>>
endobj

14 0 obj
<</Type/Page/Parent 46 0 R/Resources 93 0 R/MediaBox[0 0 595.303937007874 841.889763779528]/Annots[
42 0 R 43 0 R ]
/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 15 0 R>>
endobj

17 0 obj
<</Type/Page/Parent 46 0 R/Resources 93 0 R/MediaBox[0 0 595.303937007874 841.889763779528]/Annots[
25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R 38 0 R 39 0 R
40 0 R 41 0 R ]
/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 18 0 R>>
endobj

20 0 obj
<</Type/Page/Parent 46 0 R/Resources 93 0 R/MediaBox[0 0 595.303937007874 841.889763779528]/Annots[
24 0 R ]
/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 21 0 R>>
endobj

46 0 obj
<</Type/Pages
/Resources 93 0 R
/MediaBox[ 0 0 595.303937007874 841.889763779528 ]
/Kids[ 1 0 R 5 0 R 8 0 R 11 0 R 14 0 R 17 0 R 20 0 R ]
/Count 7>>
endobj

23 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[279.743 293.289 329.307 301.439]/A<</Type/Action/S/URI/URI(http://www.oolite.org/)>>
>>
endobj

24 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[318.793 615.339 462.007 623.139]/A<</Type/Action/S/URI/URI(http://creativecommons.org/licenses/by-nc-sa/3.0/)>>
>>
endobj

25 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[242.293 82.489 319.357 90.289]/A<</Type/Action/S/URI/URI(http://www.aegidian.org/bb)>>
>>
endobj

26 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[387.643 129.289 474.207 137.089]/A<</Type/Action/S/URI/URI(mailto:oolite.bug.reports@gmail.com)>>
>>
endobj

27 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[175.143 129.289 303.157 137.089]/A<</Type/Action/S/URI/URI(https://github.com/OoliteProject/oolite/issues)>>
>>
endobj

28 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[106.343 160.489 234.707 168.289]/A<</Type/Action/S/URI/URI(https://creativecommons.org/licenses/by/3.0/)>>
>>
endobj

29 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[270.793 168.289 412.607 176.089]/A<</Type/Action/S/URI/URI(https://freesound.org/people/jobro/sounds/35677/)>>
>>
endobj

30 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[106.343 176.089 234.707 183.889]/A<</Type/Action/S/URI/URI(https://creativecommons.org/licenses/by/3.0/)>>
>>
endobj

31 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[298.643 183.889 469.757 191.689]/A<</Type/Action/S/URI/URI(https://freesound.org/people/bubaproducer/sounds/151022/)>>
>>
endobj

32 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[106.343 191.689 255.307 199.489]/A<</Type/Action/S/URI/URI(https://creativecommons.org/publicdomain/zero/1.0/)>>
>>
endobj

33 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[292.493 199.489 455.957 207.289]/A<</Type/Action/S/URI/URI(https://freesound.org/people/notyermom/sounds/434834/)>>
>>
endobj

34 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[106.343 247.389 183.407 255.189]/A<</Type/Action/S/URI/URI(http://www.aegidian.org/bb)>>
>>
endobj

35 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[374.843 270.789 482.607 278.589]/A<</Type/Action/S/URI/URI(https://github.com/OoliteProject/oolite)>>
>>
endobj

36 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[262.093 278.589 363.007 286.389]/A<</Type/Action/S/URI/URI(http://wiki.alioth.net/index.php/OXP)>>
>>
endobj

37 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[228.143 286.389 349.307 294.189]/A<</Type/Action/S/URI/URI(http://wiki.alioth.net/index.php/Oolite_FAQ)>>
>>
endobj

38 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[180.793 294.189 321.457 301.989]/A<</Type/Action/S/URI/URI(http://wiki.alioth.net/index.php/Oolite_Main_Page)>>
>>
endobj

39 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[281.243 301.989 298.657 309.789]/A<</Type/Action/S/URI/URI(http://www.oolite.org/)>>
>>
endobj

40 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[231.743 301.989 281.307 309.789]/A<</Type/Action/S/URI/URI(http://www.oolite.org/)>>
>>
endobj

41 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[211.893 535.389 376.057 543.189]/A<</Type/Action/S/URI/URI(http://wiki.alioth.net/index.php/Hidden_Settings_in_Oolite)>>
>>
endobj

42 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[324.743 141.339 465.207 148.689]/A<</Type/Action/S/URI/URI(http://www.gnustep.org/plist-0_9.xml)>>
>>
endobj

43 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[324.743 515.539 465.207 522.889]/A<</Type/Action/S/URI/URI(http://www.gnustep.org/plist-0_9.xml)>>
>>
endobj

44 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[222.993 658.539 337.657 666.339]/A<</Type/Action/S/URI/URI(http://wiki.alioth.net/index.php/OXP_List)>>
>>
endobj

45 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[329.243 293.289 346.657 301.439]/A<</Type/Action/S/URI/URI(http://www.oolite.org/)>>
>>
endobj

94 0 obj
<</Type/Catalog/Pages 46 0 R
/OpenAction[1 0 R /XYZ null null 0]
/ViewerPreferences<</DisplayDocTitle true
>>
/Lang(en-GB)
>>
endobj

95 0 obj
<</Title<FEFF004F006F006C0069007400650052006500610064004D0065>
/Author<FEFF006200610072006B006E0069006B006B>
/Subject<FEFF0051007500690063006B00200053007400610072007400200047007500690064006500200074006F002000740068006500200063006F006D00700075007400650072002000670061006D00650020004F006F006C006900740065>
/Keywords<FEFF0043006F006D00700075007400650072002000470061006D0065002C002000530070006100630065002000470061006D0065002C0020004F006F006C006900740065002C00200045006C006900740065002C002000470061006D0065002D0070006C006100790020004700750069006400650073002E>
/Creator<FEFF005700720069007400650072>
/Producer<FEFF004C0069006200720065004F0066006600690063006500200037002E0033>
/CreationDate(D:20230703124303+02'00')>>
endobj

xref
0 96
0000000000 65535 f 
0000212536 00000 n 
0000000019 00000 n 
0000010211 00000 n 
0000010233 00000 n 
0000212731 00000 n 
0000050725 00000 n 
0000062178 00000 n 
0000212919 00000 n 
0000062200 00000 n 
0000074248 00000 n 
0000213089 00000 n 
0000074271 00000 n 
0000086583 00000 n 
0000213261 00000 n 
0000086606 00000 n 
0000095886 00000 n 
0000213458 00000 n 
0000095908 00000 n 
0000107937 00000 n 
0000213760 00000 n 
0000107960 00000 n 
0000120428 00000 n 
0000214116 00000 n 
0000214267 00000 n 
0000214445 00000 n 
0000214598 00000 n 
0000214762 00000 n 
0000214937 00000 n 
0000215110 00000 n 
0000215287 00000 n 
0000215460 00000 n 
0000215645 00000 n 
0000215824 00000 n 
0000216006 00000 n 
0000216161 00000 n 
0000216329 00000 n 
0000216494 00000 n 
0000216666 00000 n 
0000216844 00000 n 
0000216995 00000 n 
0000217146 00000 n 
0000217333 00000 n 
0000217498 00000 n 
0000217663 00000 n 
0000217833 00000 n 
0000213950 00000 n 
0000120451 00000 n 
0000122476 00000 n 
0000122498 00000 n 
0000122685 00000 n 
0000122985 00000 n 
0000123150 00000 n 
0000130502 00000 n 
0000130524 00000 n 
0000130721 00000 n 
0000131207 00000 n 
0000131536 00000 n 
0000135085 00000 n 
0000135107 00000 n 
0000135308 00000 n 
0000135668 00000 n 
0000135893 00000 n 
0000147942 00000 n 
0000147965 00000 n 
0000148153 00000 n 
0000148832 00000 n 
0000149341 00000 n 
0000160470 00000 n 
0000160493 00000 n 
0000160685 00000 n 
0000161331 00000 n 
0000161810 00000 n 
0000169045 00000 n 
0000169067 00000 n 
0000169268 00000 n 
0000169630 00000 n 
0000169860 00000 n 
0000176338 00000 n 
0000176360 00000 n 
0000176555 00000 n 
0000176856 00000 n 
0000177026 00000 n 
0000200652 00000 n 
0000200675 00000 n 
0000200866 00000 n 
0000201429 00000 n 
0000201839 00000 n 
0000211350 00000 n 
0000211372 00000 n 
0000211564 00000 n 
0000212017 00000 n 
0000212323 00000 n 
0000212437 00000 n 
0000217984 00000 n 
0000218127 00000 n 
trailer
<</Size 96/Root 94 0 R
/Info 95 0 R
/ID [ <31BAE957EC4FEE1625FC564A0034FA5D>
<31BAE957EC4FEE1625FC564A0034FA5D> ]
/DocChecksum /46175E035933F5AA602668FC54BD7527
>>
startxref
218856
%%EOF

Doc/README_LINUX.TXT

Oolite-Linux
============

This repository contains the files required to build Oolite for Linux,
GNUstep and OpenGL. It should be easily portable to FreeBSD.

0. Pre-requisites

- Objective-C. On Fedora Core, 'up2date -i gcc-objc' installs.

- SDL Development libraries. (Currently used only for sound). Most
distros have this pre-installed or as an easy-to-install package.
Also, SDL_Mixer and SDL_Image are required (they are standard SDL
libraries, but most Linux distros don't install them by default)

- GNUstep Development libraries. I advise you build GNUstep from source
since some prepackaged versions don't have a new enough NSOpenGLView.
It builds easily from source so don't panic.

Tip: Get the GNUstep Startup Version. Everything you need in one
package. Make sure you do:

PATH=$PATH:.

before running make when you build GNUstep Startup, because it depends
on running a shell script in the current directory.

Hardware OpenGL support is a must. Oolite linux was tested on the
following machines - a 2GHz P4 with a GeForce 4ti and an old Compaq
733MHz P3 with ATi Radeon Mobility. It ran fine on both machines.
I have heard reports of bad things happening with ATi graphics
cards, but only off one person (textures didn't display), and another
person with a Matrox graphics card had problems with the text.

Building
========
Type:
make

If this fails and you're certain you have GNUstep's development
stuff installed, make sure you have this in your .bashrc or
equivalent:

. /usr/GNUstep/System/Library/Makefiles/GNUstep.sh

GNUstep tells you this if you build it but you won't have been told
if you've installed your distro's GNUstep binaries :-)

Running
=======
Type:
openapp oolite

or
openapp oolite.debug
if you built with 'make debug=yes'.

Troubleshooting
===============
I suggest you go through some of the GNUstep tutorials and make sure these
build and run successfully to ensure your build and runtime environment
is sane. Also, there's a little (and rather nasty) environment tester
on ftp.alioth.net/oolite/gl-gnustep.tar.gz. If you're having problems
I recommend you get this running first; it's relatively simple and should
expose any problems your installation has without possible Oolite problems
clouding your view.

Is it borked for you?
=====================
If you find it's borked, please post a message on the oolite-linux
forum (see http://aegidian.org/bb). Please provide a backtrace if you
have one, screenshots, and describe weirdness with sound. Also provide
log messages from the console. Better still, if you have a fix, send
us the patch!

Modifications from OSX Oolite
=============================

Makefiles:
GNUmakefile and GNUmakefile.postamble.
The former controls compilation and linking, and the latter copies
data files (PNG images, plists, dat files) into oolite.app/Contents/Resources.
PlayerEntity_Additions.m, PlayerEntity_contracts.m, ShipEntity_AI.m -
   These just #include "PlayerEntity (contracts).m" etc. because
   spaces and brackets really suck in the Makefile and shell.
#ifdefs -
   All over the code you'll see #ifdef GNUSTEP ... #else .... #endif
   If you grep for these, you can see where work has to be done.
   I've usually put a TODO: comment line in these (many of them are not
   filled in). I've not #ifdef'd out any methods - I've left at least
   a stub if there's nothing to put in there .

Addition of Comparison.m/h from ObjectiveLib 
(see http://objectivelib.sourceforge.net). ObjectiveLib is an LGPL'd 
set of libraries to add functionality to GNUstep. Comparison.h/m 
implements a category of NSObject that adds isEqualTo:, isGreaterThan:,
isGreaterThanOrEqualTo:, isLessThan:, isLessThanOrEqualTo:, isNotEqualTo:
methods. It looked like a relatively simple category, so rather
than creating a dependency on the whole of ObjectiveLib, I decided
to just add these two files.

Sound uses SDL instead of the AppKit's sound (the sound daemon crashes).
Graphics use SDL instead of NSOpenGLView.


Notes for the terminally insane
===============================
See PORTING.TXT - it's useful to read this if you're tinkering on Linux
and not porting. It may save you grief.

Mac-specific/DataFormatters/README.txt

This project builds a data formatter plug-in for Xcode which sets up debugger
data formatters for various Oolite classes and structs, as well as most JSAPI
types.

All the actual data formatters are set up in CustomDataViews.plist; the bundle
is just a stub to allow it to be installed without overwriting/modifying your
main CustomDataViews.plist (which is set up automatically by Xcode).

To install, cd to this directory and run "xcodebuild install". Alternatively,
build from Xcode and copy the bundle to:
~/Library/Application Support/Developer/Shared/Xcode/CustomDataViews/

Mac-specific/OCUnitTests/README.txt

This project contains OCUnit/SenTestingKit unit tests.

These can be run from within the main Xcode project by selecting Product → Test
with any of the predefined schemes selected. They will also run at the end of
any TestRelease or Deployment build (including nightlies).

Test failures appear as error messages in the Issues Navigator.


A very old version of OCUnit which nominally supports GNUstep can be found
here: http://www.sente.ch/software/ocunit/

Unfortunately, the names of all the testing macros have changed since then and
that version apparently only works with the Apple Objective-C runtime anyway,
so without a significant amount of work the unit tests are Mac-only.

README.md

[![build-all](https://github.com/OoliteProject/oolite/actions/workflows/build-all.yaml/badge.svg)](https://github.com/OoliteProject/oolite/actions/workflows/build-all.yaml)

[![GitHub release](https://img.shields.io/github/release/OoliteProject/Oolite.svg)](https://github.com/OoliteProject/Oolite/releases/latest)

| Windows                                                                                                                                                                   | Linux                                                                                                                                                                                   | OSX                                                                                                                                                                                   |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/Oolite-1.90_x64.exe.svg)](https://github.com/OoliteProject/oolite/releases/latest) | [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/oolite-1.90.linux-x86_64.tgz.svg)](https://github.com/OoliteProject/oolite/releases/latest)      | [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/oolite-1.90.zip.svg)](https://github.com/OoliteProject/oolite/releases/latest)                 |
 [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/Oolite-1.90_x86.exe.svg)](https://github.com/OoliteProject/oolite/releases/latest) | [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/oolite-1.90.linux-x86.tgz.svg)](https://github.com/OoliteProject/oolite/releases/latest)         | [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/Oolite-1.90-Mac-TestRelease.zip.svg)](https://github.com/OoliteProject/oolite/releases/latest) |
|                                                                                                                                                                           | [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/oolite-1.90-test.linux-x86_64.tgz.svg)](https://github.com/OoliteProject/oolite/releases/latest) |                                                                                                                                                                                       |
|                                                                                                                                                                           | [![Github release](https://img.shields.io/github/downloads/OoliteProject/Oolite/latest/oolite-1.90-test.linux-x86.tgz.svg)](https://github.com/OoliteProject/oolite/releases/latest)    |                                                                                                                                                                                       |

![Oolite Screenshot](https://addons.oolite.space/i/gallery/oxp/large/another_commander-210210_LeavingCoriolisAgain.png)

Oolite can be heavily customized via expansions. These modify the gameplay, add ships, improve graphics - the
possibilities are almost endless:

![Oolite Customized](https://addons.oolite.space/i/gallery/oxp/large/another_commander_ViperNew02.png)

Please join the [Oolite Bulletin Board](https://bb.oolite.space/), a friendly community of Oolite fans
and developers!

## Installing Oolite

You can download the latest version from [here](https://github.com/OoliteProject/oolite/releases).

### Windows

The Windows NSIS installer is named `OoliteInstall-XXX-win.exe` where XXX is a version number.
Double click the downloaded file to run the installer.

### Linux

Linux has Flatpak and AppImage versions. The Flatpak is named `space.oolite.Oolite_XXX.flatpak`
where XXX is a version number. Many Linux package managers support Flatpak so you should be able to
double click the downloaded file to install it.

The AppImage is named `Oolite_XXX-x86_64.AppImage` where XXX is a version number. Download this
file to where you would like it stored, make it executable and run, for example by typing

```bash
chmod +x Oolite_XXX-x86_64.AppImage
./Oolite_XXX-x86_64.AppImage
```

## Playing Oolite

Information about playing Oolite can be found [here](https://oolite.readthedocs.io/en/latest/).

For more information, see also [oolite.space](http://www.oolite.space/) and
[Elite Wiki](http://wiki.alioth.net/index.php/Oolite_Main_Page).

## Building from Source

We welcome developers to work on Oolite! If you wish to build the project from source, please follow
the instructions below. Note that the scripts require sudo for activities like installing dependent
libraries built from source and for installing packages on some Linux distros. If you run into
difficulties, you can seek help on the [Oolite Bulletin Board](https://bb.oolite.space/).

API documentation is available [here](https://oolite.readthedocs.io/en/latest/api/html/).

### Git

The Oolite source is available from GitHub. The first step is to install git if you don't already
have it installed as it is required to obtain and build Oolite. With Git installed, check out the
Oolite repository and its submodules:

```bash
git clone --filter=blob:none --recurse-submodules https://github.com/OoliteProject/oolite.git
cd oolite
```

### Windows

After installing git and checking out the Oolite repository and its submodules, double click `Run Me`
in ShellScripts/Windows or run in a command prompt:

```cmd
ShellScripts\Windows\setup.cmd
```

This will install MSYS2 which provides various MinGW environments. You will need to enter the
install location for MSYS2 and whether you want the Clang build (recommended) or GCC build.

The Clang build uses the UCRT64 environment, while the GCC build uses the MINGW64 environment.

### Linux

After installing git and checking out the Oolite repository and its submodules, run the following
to check out the dependencies of Oolite that need to be built from source:

```bash
ShellScripts/Linux/checkout_deps.sh
```

Next run the following to install required packages and build dependencies (you can replace sudo
with other methods that escalate privileges if you prefer):

```bash
sudo ShellScripts/Linux/install_deps_root.sh
```

### Building Oolite

Next run this in your bash or MSYS2 prompt to build Oolite:

```bash
ShellScripts/common/build_oolite.sh release
```

The completed build (executable and games files) can be found in the Oolite.app directory.

Subsequently, you can clean and build as follows:

```bash
make -f Makefile clean
make -f Makefile release -j$(nproc)
```

On Linux, you will need to run this beforehand: `source /usr/local/share/GNUstep/Makefiles/GNUstep.sh`

On Windows, this is set up be default in the shell: `source $MINGW_PREFIX/share/GNUstep/Makefiles/GNUstep.sh`

Other targets are release-deployment for a production release and release-snapshot for a debug release.

### Other Linux Make Targets

This target builds an AppImage for testing which can be found in build:

```bash
make -f Makefile pkg-appimage -j$(nproc)
```

The target pkg-appimage-deployment is the production release, while pkg-appimage-snapshot is for debugging.

This target builds a Flatpak which can be found in build:

```bash
make -f Makefile pkg-flatpak -j$(nproc)
```

### Mac OS

Intel-based Macs can run old builds of Oolite, but current Macs are unsupported. It is hoped that they can be supported
in future.

### Objective-C

Oolite is written in Objective-C although there is also some C and C++ code in the codebase. It was
originally coded on Mac, but was ported to Windows and Linux by way of the GNUstep runtime which
provides a similar API to what is available on Mac. Objective-C is supported by modern IDEs like
CLion and Visual Studio Code. The language can be easily picked up by programmers familiar with C
or C++ with which it is interoperable.

### Troubleshooting

- If you get errors like `fatal error: jsapi.h: No such file or directory`, there was probably an issue with checking
  out the submodules.

- If you can't see any textures, try deleting the following files, and compile again although these are already excluded
  from modern builds.

```bash
rm deps/Linux-deps/include/png.h
rm deps/Linux-deps/include/pngconf.h
```

- If you get compiler errors, you can try compiling with:

```bash
make -f Makefile release OBJCFLAGS="-fobjc-exceptions -Wno-format-security" -j$(nproc)
```

## Contents of repository

Oolite for all platforms can be built from this repository. Here is a quick
guide to the source tree.

- **debian**:  Files to enable automatic setup under Linux using dpkg (Debian package manager) tools
- **DebugOXP**:  [Debug.oxp](http://wiki.alioth.net/index.php/Debug_OXP), the expansion pack that enables console
  support in debug and test release builds
- **deps**
    - **Cocoa-deps**:  Dependencies for Mac OS X
    - **Cross-platform-deps**:  Dependencies for platforms other than Mac OS X
    - **Linux-deps**:  Dependencies for Linux on x86 and x86_64 processors
    - **URLs**:  URLs used for binary dependencies on Mac OS X
    - **Windows-deps**:  Dependencies for Windows on x86 and x86_64 processors
- **Doc**:  Documentation (including user guides)
- **ShellScripts**:  Scripts to build from source on Windows and Linux
- **installers**:  Files used to create various installers
- **Mac-specific**:  Additional projects used only on Mac OS X
    - **DataFormatters**:  Debugger configurations for Xcode
    - **DebugBundle**:  Implements
      the [Debug menu and in-app console](http://wiki.alioth.net/index.php/Debug_OXP#Mac_OS_X-specific_features)
    - **OCUnitTest**:  A small number of unit tests
    - **Oolite-docktile:**  An embedded plug-in which implements the Oolite dock menu when Oolite is not running
    - **Oolite-importer**:  A Spotlight importer to make saved games and OXPs searchable
- **Oolite.xcodeproj**:  The OS X Xcode project to build Oolite
- **Resources**:  Game assets and resource files for Mac and GNUstep application bundles
- **Schemata**:  Plist schema files for the [OXP Verifier](http://wiki.alioth.net/index.php/OXP_howto#OXP_Verifier)
- **src**:  Objective-C and C sources, incuding header files
    - **BSDCompat**:  Support for BSDisms that gnu libc doesn't have (strl*)
    - **Cocoa**:  Files that are only compiled on Mac OS X
    - **Core**:  Files that are compiled on all platforms
    - **SDL**:  Files that are only compiled for platforms that use SDL
- **tests**:  A mixed bag of test cases for manual testing and ad-hoc code tests.
- **tools**:  Various tools for preparing files, builds, releases etc.

Resources/README.TXT

oolite-data
===========

This resources folder contains all the data that oolite needs when you run it - sounds,
textures, default settings, etc.

To modify sounds, textures and settings, use the AddOns directory, rather than modify
these files directly. For more information on how to do so, follow the guidelines found
at the following URL:

http://wiki.alioth.net/index.php/OXP_howto

Or ask on Oolite's Bulletin Board:

https://bb.oolite.space

Schemata/README.txt

Schemata
=======

This folder contains property list schemata for the various plists used in Oolite.

For more information, see src/Core/OXPVerifier/OOPListSchemaVerifier.h and tools/plistSchemaVerifier.

deps/Linux-deps/README.TXT

Oolite Binary Release
=====================


Here are some things that you need to know, which will get you out of possible
mishaps.

Keyboard shortcut F12 toggles full screen/windowed mode.

Full screen or windowed mode as well as full screen mode resolutions may be 
selected in "Game Options..." from the main game menu (F2 key). The settings
you select will be saved to your user defaults.

Some older (much older) OpenGL cards can't cope with Oolite in higher 
resolutions and graphics rendering modes. This may result in textures not 
properly rendered, text rendered as blocks, visual artifacts to be displayed 
or low perfomance and frame rate. You may try various settings in the 
"Game Options..." menu, to check if any of these issues are addressed.

Most newer cards work just fine in all supported resolutions and graphics
detail settings. In any case we invite you to visit the Oolite bulletin board
at http://aegidian.org/bb/index.php and post any issue, concern or suggestion.
Our community is known as being "The friendliest board this side of Riedquat".



Troubleshooting audio issues
============================
If you encounter sound issues with Oolite, it could be that the prepackaged 
libraries that come with Oolite are not fully compatible with your system. 
A workaround is to force Oolite to use your system's libraries instead of 
the prepackaged ones.

The prepackaged Oolite libraries are located under the  
<Oolite installation folder>/oolite-deps/lib/ folder.

If any of the following suggestions do not resolve the issue then join us at 
our Oolite-Linux community at http://aegidian.org/bb/viewforum.php?f=9
and share your case with us. We have a thing for helping out fellow Commanders
in distress.

1. Oolite speech synthesis troubleshooting
------------------------------------------
To correct issues with Oolite speech synthesis go to the oolite-deps/lib 
folder and try the following: 

Workaround A: Use the alternative PulseAudio speech synthesis library.
$ cp -p libespeak.so.1 libespeak.so.1.portaudio
$ cp -p libespeak.so.1.pulseaudio libespeak.so.1
Now execute Oolite. If this doesn't work try the following:

Workaround B: Force Oolite to use your system's libespeak library.
First make sure that you have libespeak.so.1 installed in your system. Then
"hide" the Oolite libespeak prepackaged library by going into the
oolite-deps/lib folder and executing the following:
$ mv libespeak.so.1 libespeak.so.1.oolite
Now execute Oolite.

2. No Audio or Oolite fails to execute
--------------------------------------
2a. First make sure that you have libSDL-1.2.so.0 installed in your system. Then
"hide" the Oolite libSDL prepackaged library by going into the oolite-deps/lib 
folder and executing the following: 
$ mv libSDL-1.2.so.0 libSDL-1.2.so.0.oolite
Now execute Oolite. If this doesn't work then restore Oolite prepackaged libSDL:
$ mv libSDL-1.2.so.0.oolite libSDL-1.2.so.0 
and try the following:

2b. First make sure that you have libopenal.so.1 installed in your system. Then
"hide" the Oolite libopenal prepackaged library by going into the
oolite-deps/lib folder and executing the following:
$ mv libopenal.so.1 libopenal.so.1.oolite
Now execute Oolite. 

If this doesn't work either, try hiding both libSDL and libopenal Oolite
prepackaged libraries and execute Oolite again.



Updating to new versions
========================
Once installed, Oolite can be updated to the latest release, by executing 
the oolite-update script.

This resides in either /usr/local/bin/ for system-wide Oolite installations 
or in ~/GNUstep/Applications/Oolite/ for home-folder installations.

Running this updater will be considerably faster than downloading the full 
new package. "oolite-update" uses the rsync utility software and network 
protocol, and will update your Oolite installation from any version >= 1.75.2 
to the latest release. 



Folders that get created during execution
=========================================
Note: Please note that the folders described in this paragraph are not 
removed when you uninstall Oolite. They are considered as user folders 
(e.g. AddOns, screenshots, savegames with player's in-game status, game
settings, etc.) since they contain files generated with the Commander's own
pain and blood. You will have to manually remove them, if you believe that 
you do not need them and that you will not need them even if you reinstall 
Oolite in the future.

When you run Oolite for the first time a ~/GNUstep/ (~ stands for your home 
folder path) folder will be created into your home folder. The GNUstep 
backend needs this. 

If you decide to use the "Manage Expansion Packs" functionality the 
~/GNUstep/Library/ApplicationSupport/Oolite/ManagedAddOns/ folder will be
created to store the AddOns that you install from within the game itself.
This is the only folder (from the folders described in this section) that 
the uninstaller will remove in case it finds it empty.

A ~/.Oolite/Logs/ folder is created to store the application Logs folder. 
When Oolite is installed as a system-wide application, the .Oolite folder 
may also be used to store OXPs visible only by the specific user 
(~/.Oolite/AddOns.); see the "Adding AddOns" section below for more details.

A ~/.Oolite/.oolite-run file is also created at first run and its existence 
supresses the display of this README.

A ~/oolite-saves/ folder is created when you save your game status as a 
Commander. 

Finally a ~/oolite-saves/snapshots/ folder is created when you grab an 
in-game screenshot (* key) for the first time. 



Saved games
===========
Saved games are all saved in ~/oolite-saves/ in your home folder. You can 
copy all the existing .oolite-save files (for example, from a Macintosh) 
into this folder, and they will appear in the 'Load Commander' menu screen 
in the game.

However, if you decide to install add-ons, make sure that if you buy an
add-on ship you don't remove it, because your save game will stop working
if the ship it's based-on doesn't exist!



Adding AddOns
=============
There are over 500 game add ons available - missions, ships etc.
To find out what is currently available, we recommend you start by looking
at the OXP section of the Oolite wiki: http://wiki.alioth.net/index.php/OXP

To install an OXP, just copy the .oxp folder into the Oolite "AddOns" folder.
Next time you run Oolite, the OXP will be loaded.

If Oolite is installed system-wide then you have the following options:
A. OXPs visible by all users:
        Copy the .oxp folder in the <Oolite installation folder>/AddOns/
B. OXPs visible only to a user:
        Copy the .oxp folder in the ~/.Oolite/AddOns/ 
Options A and B can be combined. Oolite will look for add-ons in both 
folders.

If Oolite is installed in your home-folder you may either copy the .oxp folder
into ~/GNUstep/Applications/Oolite/AddOns/ or into ~/.Oolite/AddOns/ . In this
case putting some add-ons in one folder and some add-ons in another does not
have any obvious use.

It is suggested that you keep your OXPs in one AddOns folder.

Caution: if you save a game after buying a ship that was in an OXP, then if you
subsequently remove the OXP, that commander file will be rendered useless!



What are the dependencies that are packaged?
============================================
Since Oolite for Linux 1.75.2-beta release, a new distribution-neutral 
self-extractable package format has been introduced. The library dependencies 
are packaged within the installer. They are installed under the Oolite/ tree 
structure and are only visible by Oolite, thus not messing at all with your 
system's own libaries.

So far, we've tested the pre-packaged dependencies on vanilla installations of
Ubuntu, Mint, Debian, Mandriva, Fedora, OpenSuse and on LinpusLite (!!!) with
just the normal beginner's installation (i.e. accepting all the defaults for 
the GNU/Linux distro installed). It should work on any Linux distribution, 
however for vintage distros, an old libc can scupper you; it won't run on 
RedHat 8 for instance because libc is just too old. 

It will also run on Knoppix (if you have somewhere writeable to install it).
Please let us know what distro you're using and whether it worked or not via 
the Oolite-Linux forum (see the link below under 'If it's borked').

The pre-packaged dependencies that come with Oolite are:
libespeak.so.1 
(compiled to use libportaudio.so.2 also pre-packaged)

libespeak.so.1.pulseaudio 
(compiled to use PulseAudio as an alternative if libespeak.so.1 fails)

libffi.so.4
libgcrypt.so.20
libgmp.so.10
libgnustep-base.so.1.20 (gnustep-base-1.20.1 built with TLS support)
libgnutls.so.30
libgpg-error.so.0
libhogweed.so.4
libnettle.so.6
libnspr4.so.0d
libobjc.so.2
libogg.so.0
libopenal.so.1 (openal-soft-1.15.1)
libplc4.so.0d
libplds4.so.0d
libpng14.so.14 (libpng-1.4.7)
libportaudio.so.2 (PortAudio stable v19 released 2011-03-26)
libSDL-1.2.so.0 (SDL-1.2.14)
libvorbisfile.so.3
libvorbis.so.0
libz.so.1 

Backward compatibility with GLIBC_2.7 Linux systems is achieved using a 
vanilla installation of Ubuntu 8.04.4. The following source tarballs have 
been used to build the additional libraries:
http://ftpmain.gnustep.org/pub/gnustep/core/gnustep-make-2.0.8.tar.gz
http://ftpmain.gnustep.org/pub/gnustep/core/gnustep-base-1.20.1.tar.gz
http://www.libsdl.org/release/SDL-1.2.14.tar.gz
http://kcat.strangesoft.net/openal-releases/openal-soft-1.15.1.tar.bz2
http://prdownloads.sourceforge.net/libpng/libpng-1.4.7.tar.gz?download
https://sourceforge.net/projects/libpng/files/zlib/1.2.8/zlib-1.2.8.tar.gz/download
http://www.portaudio.com/archives/pa_stable_v19_20110326.tgz
http://downloads.sourceforge.net/project/espeak/espeak/espeak-1.43/espeak-1.43.03-source.zip?use_mirror=kent
https://gmplib.org/download/gmp/gmp-6.1.0.tar.lz
ftp://ftp.gnutls.org/gcrypt/gnutls/v3.4/gnutls-3.4.15.tar.xz
https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.7.3.tar.bz2
https://gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-1.24.tar.bz2
https://ftp.gnu.org/gnu/nettle/nettle-3.2.tar.gz

All of these dependencies are pretty straightforward to compile.
If you're constructing a package for a non-x86 or non-Linux platform,
take a look in https://github.com/OoliteProject/oolite-linux-dependencies 
for the libraries (dynamic and static) and headers you'll need to copy there. 



Call for maintainers
====================
If you're willing to maintain any non-x86 arch and any non-Linux OS (Oolite 
is at least known to run on FreeBSD) please let us know at: 
http://aegidian.org/bb/viewforum.php?f=5



If it's borked
==============
Please report it in the Oolite-Linux forum. Please include screen snapshots 
for graphics weirdness, and clear descriptions of sound weirdness. 
Include any logs in the terminal window. If you launched Oolite from an 
icon, you may need to start a terminal and run Oolite from there in order 
to see any further O/S error messages. The Oolite-Linux forum is here:
http://aegidian.org/bb/viewforum.php?f=9



Talking about it, reporting bugs etc.
=====================================
The Oolite bulletins board can be found here:
http://aegidian.org/bb



Credits
=======
Original OS X game: Giles Williams
Linux port: David Taylor, Giles Williams and Dylan Smith

...and of course the GNUstep project and the SDL, OpenAL people, without 
which the Linux and Win32 ports would not have been possible.

deps/Linux-deps/Readme.md

# Oolite Linux dependencies
This repository contains binary dependencies used to build Oolite for Linux (32-bit and 64-bit x86). It is included as a submodule in the main Oolite repository.

The documented build process for Oolite for Linux will pull in these pre-built dependencies with no additional work required. The rest of this file documents how to reproduce the changes made.


## Modifications to external libraries' source code for running Oolite
The various ports of Oolite are using a number of external libraries for graphics, sound, input and event handling. Throughout development, certain changes to the source code of these libraries have been deemed necessary, either to enable Oolite to run in a more efficient and independent manner, or simply to fix issues that occurred as a result of these external libraries themselves. Of these libraries, the ones that have to be rebuilt specifically for Oolite, together with the main reasons/areas changed for this reason are:

1. SpiderMonkey v1.85 (all platforms) - certain JS macro definitions required by Oolite not guaranteed or non-existent in standard library.

The changes made in the source code of each of these libraries are as follows:

### SpiderMonkey v1.85 (all platforms)
Specific build settings for Oolite are required. Library rebuilt with the following macros defined as shown below:
* `JS_THREADSAFE` defined on Mac and Linux debug builds.
* `MOZ_TRACE_JSCALLS` defined in order to enable full JavaScript profiling.
The entire source code of the library can be downloaded from ftp://anonymous@ftp.mozilla.org/pub/firefox/releases/4.0/source/firefox-4.0.source.tar.bz2

deps/URLs/README

These files contain download URLs for various dependencies. They are used
by the Mac OS X build system to download dependencies automatically (see
deps/Cocoa-deps/scripts). The first line must be an URL which can be
downloaded by curl and expanded by tar. Any additional lines will be
ignored. Currently, the second line is the original URL for files which are
mirrored.

deps/Windows-deps/Readme.md

# Oolite Windows dependencies
This repository contains binary dependencies used to build Oolite for Windows. It is included as a submodule in the main Oolite repository.

Note: As of October 2022, the 32-bit version of the game is no longer supported. 32-bit libraries are frozen and development continues with the 64-bit versions only.


The documented build process for Oolite for Windows will pull in these pre-built dependencies with no additional work required. The rest of this file documents how to reproduce the changes made.


## Modifications to external libraries' source code for running Oolite
The various ports of Oolite are using a number of external libraries for graphics, sound, input and event handling. Throughout development, certain changes to the source code of these libraries have been deemed necessary, either to enable Oolite to run in a more efficient and independent manner, or simply to fix issues that occurred as a result of these external libraries themselves. Of these libraries, the ones that have to be rebuilt specifically for Oolite, together with the main reasons/areas changed for this reason are:

1. gnustep-base v1.20.1 – bug in `NSInteger` definition, change to dictionary format of `NSUserDefaults`, fix for integer truncation of integers to 32-bit when parsing XML plists (bug #32495 on the gnustep.org bug tracker) and changes to facilitate native Objective-C exception support. Also, fix bug in the stack grabbing code at NSDebug.m so that correct stack traces can be obtained also on Windows XP and later.
2. SDL v1.2.13 – window resizing issues, backported fix for setting gamma crash, haptic devices support, mousewheel delta support.
3. SpiderMonkey v1.85 – certain JS macro definitions required by Oolite not guaranteed or non-existent in standard library.
4. eSpeak v1.43.03 – Special build of the Windows speech synthesis libespeak.dll to enable asynchronous playback. Also, defaults the eSpeak data directory to Resources/espeak-data.
5. SDL_mixer v1.2.7 – Bug fix for static heard over Ogg Vorbis music when music loops. [Obsolete since v1.80]

The changes made in the source code of each of these libraries are as follows:

### gnustep-base v1.20.1
GSConfig.h (build generated file): In the section reading
```C
/*
 * Integer type with same size as a pointer
 */
typedef	unsigned int gsuaddr;
typedef	int gssaddr;
typedef	gsuaddr gsaddr;
```

Change
```C
typedef	gsuaddr gsaddr;
```
to
```C
typedef	gssaddr gsaddr;
```
to fix incorrect definition of NSInteger. 

The `NSUserDefaults` system dictionary (.GNUstepDefaults) is written in XML format in GNUstep 1.20.1. This is inconvenient for Oolite, where the more human-friendly OpenStep format for plists is used. The `static BOOL writeDictionary(NSDictionary *dict, NSString *file)` function, at around line 157 of the NSUserDefaults.m file is therefore changed to read as below:
```objc
data = [NSPropertyListSerialization dataFromPropertyList: dict
	       //format: NSPropertyListXMLFormat_v1_0  // no XML format, use OpenStep instead
	       format: NSPropertyListOpenStepFormat
	       errorDescription: &err];
```
	       
When parsing XML plists, integers are truncated to 32-bit, effectively prohibiting the correct parsing of `long long` or `unsigned long long` values. The fix applied in the gnustep-base-1_20.dll distributed with Oolite in order to address this is:
a) Changing line 309 of NSPropertyList.m of the GNUstep base source code distribution from
```objc
ASSIGN(plist, [NSNumber numberWithInt: [value intValue]]);
```
to
```objc
ASSIGN(plist, [NSNumber numberWithLongLong: [value longLongValue]]);
```
and b) Changing line 1103 of the same file from
```objc
result = [[NSNumber alloc] initWithLong: atol(buf)];
```
to
```objc
result = [[NSNumber alloc] initWithLongLong: atoll(buf)];
```

The stack backtrace grabbing code in NSDebug.m works for Linux but fails on Windows. The GSPrivateStackAddresses function has been modified to use the WinAPI CaptureStackBacktrace method, so that it returns a correct stack backtrace also on Windows (64-bit only, 32-bit version not modified because we want to keep backwards compatibility as much as possible). The modified function is as follows:
```objc
NSMutableArray * GSPrivateStackAddresses(void)
{
  NSMutableArray        *stack;
  NSAutoreleasePool     *pool;

#if HAVE_BACKTRACE
  void                  *addresses[1024];
  int                   n = backtrace(addresses, 1024);
  int                   i;

  stack = [NSMutableArray arrayWithCapacity: n];
  pool = [NSAutoreleasePool new];
  for (i = 0; i < n; i++)
    {
      [stack addObject: [NSValue valueWithPointer: addresses[i]]];
    }
#else	// Windows code here
  unsigned              i;
  const int				kMaxCallers = 62;
  void*					callers[kMaxCallers];
  unsigned              n = CaptureStackBackTrace(0, kMaxCallers, callers, NULL);

  stack = [NSMutableArray arrayWithCapacity: n];
  pool = [NSAutoreleasePool new];
  for (i = 0; i < n; i++)
  {
	[stack addObject: [NSValue valueWithPointer: callers[i]]];
  }
#endif	// HAVE_BACKTRACE
  RELEASE(pool);
  return stack;
}
```
The GNUstep objc-1.dll runtime has been rebuilt with native Objective-C exception support. To do this on Windows, the patch which provides the `void (*_objc_unexpected_exception) (id exception)` callback hook to the runtime is required for versions of gcc older than 4.4.0. The patch can be downloaded from http://gcc.gnu.org/bugzilla/attachment.cgi?id=17365. Also, the gcc source header unwind-pe.h must be visible to exception.c in order for the build of libobjc to succeed.

The full source code of GNUstep 1.20.1 is available from
ftp://ftp.gnustep.org/pub/gnustep/core/gnustep-base-1.20.1.tar.gz

### SDL v1.2.13
The files OOSDLdll_x64.patch and OOSDLdll_x86.patch contain all the changes required for re-creating the SDL.dll used by Oolite on Windows. To apply the patches, you will need to have OoliteDevelopmentEnvironment - Light Edition installed, downloadable from https://drive.google.com/file/d/12xoD3sT1D9yDmOBPp0DKJ0HXWD4-dJjd/view?usp=sharing. Instructions for setting it up can be found at http://www.aegidian.org/bb/viewtopic.php?t=5943. Then, download the SDL-1.2.13 source code from https://sourceforge.net/projects/libsdl/files/SDL/1.2.13/SDL-1.2.13.tar.gz/download, extract the folder SDL-1.2.13 to an empty directory, then copy the appropriate patch file to that same directory. Finally, from the Oolite Development Environment console, cd to that folder and execute `patch -s -d SDL-1.2.13 -p1 < OOSDLdll_x64.patch` or `patch -s -d SDL-1.2.13 -p1 < OOSDLdll_x86.patch` and you are ready to cd to the updated SDL-1.2.13 folder and run `make` inside it in order to bvuild SDL.dll.
The changes in brief:
- Enabled window resizing without side effects like texture corruption in the Windows port of Oolite. 
- Fixed crash occurring when attempting to set the screen gamma value. This fix occurred in a later version of SDL and was backported to the version used with the Windows port of Oolite.
- Backported haptic devices support from later SDL version. This allows force feedback joysticks to work in the game.
- Added mousewheel delta support in the Windows port of Oolite for smoother mousewheel end-user experience.
- Fixed Alt key state not being recognized correctly when returning to the app via Alt-Tab. This is a fix backported from SDL 1.2.15.
- Added capability to accept float pixel types when creating OpenGL window.

### SpiderMonkey v1.85
Specific build settings for Oolite are required. Library rebuilt with `MOZ_TRACE_JSCALLS` defined in order to enable full JavaScript profiling.

The entire source code of the library can be downloaded from ftp://anonymous@ftp.mozilla.org/pub/firefox/releases/4.0/source/firefox-4.0.source.tar.bz2

### eSpeak v1.43.03
The libespeak.dll has been custom-built for the Windows port of Oolite to enable asynchronous playback and to also default the eSpeak data files folder to Resources/espeak-data. The source files that need to be changed for this to happen can be found inside oolite-windows-dependencies/OOeSpeakWin32DLLBuild. The instructions for building this library, for those interested, are as follows:
* You will need to have OoliteDevelopmentEnvironment - Light Edition installed, obtainable from the links mentioned earlier in this document.
*   Download espeak-1.43.03-source.zip from http://espeak.sourceforge.net/download.html or directly from its repository ( http://sourceforge.net/projects/espeak/files/espeak/espeak-1.43/espeak-1.43.03-source.zip/download ).
*   Unzip the file to a folder of choice, maintaining the directory structure. We'll refer to this folder as &lt;espeakSourceFolder&gt;.
*  Copy the following files from oolite-windows-dependencies/OOeSpeakWin32DLLBuild to &lt;espeakSourceFolder&gt;/src.
  - Makefile
  - gettimeofday.c
  - speak_lib.cpp
  - speech.h
* Rename the file &lt;espeakSourceFolder&gt;/src/portaudio19.h to portaudio.h.
* Copy the file speak_lib.h from &lt;espeakSourceFolder&gt;/platforms/windows/windows_dll/src to &lt;espeakSourceFolder&gt;/src.
* Start up MinGW/MSYS and change working directory to the &lt;espeakSourceFolder&gt;/src folder.
* Execute `make libespeak.dll` from the command prompt.
* The library should compile and at the end of the build you should have a file named libespeak.dll (the actual binary) and the import library file libespeak.dll.a, for use when you want to link libespeak.dll to your project.

### SDL_mixer v1.2.7
[Obsolete since v1.80]

music.c: Commented out lines 334 and 335 of `music_mixer` function.

deps/Windows-deps/x86/DLLs/pthreadGC.dll

MZ����@���	�!�L�!This program cannot be run in DOS mode.

$PEL�ļP�#Vvppk�� ����h.textTTV`0`.data`pZ@0�.rdata��\@0@.bss���0�.edata��^@0@.idata�n@0�.reloch�v@0BU����u��u�]���tO�t$�E�D$�E�$�&������t$��u��pk��u1ۉ؋]��u���]��J���u��?���$��P��pk��t���pk�(M��L��lP�1�막�U����]���pk��t*��pk��9�r
���u*��9�s�$�P1҉�pk�$��O�]���]��Ћ�pk�̍�U����D$�pk�E�D$�pk�$�O������]��HÉ�U����D$�pk�E�D$�pk�$�O��]Ð����������U��]�M�������U�����]��]��tB�$�O���t-�@1��@�@�@�@����ĉ�]��Љ�]�U����]��]�$�<*���u���$��N�1ҋ]��Љ�]É�U����u��u�]��]�4$��)��u��t�1��Q��]��u���]����鍴&��'U����]��]�u��u�$�)���u��w��r1ҋ]��Ћu���]Ð�t&U�(��]Í�U�(��]Í�U����]��]�$�L)���u��M�Z1҉�]��Љ�]Í�&��'U����]��]�$�)���u
�U��Q1ҋ]��Љ�]�U1���U�
�Q�M�]Í���U�0��U��tJ�u�M1���B]Ð��������U����u��E�u�}����}�]�t��u��]�u��}���]��$��D$�YM����t{���}���tw��s1ɉ3�s�C�C�L$�D$�4$��<��u;�{1ɍS�L$�$�|$��<��u�u1���x����4$�K=�t&��'�$�L��S���1�뇍v��'U���(�}��}�]�u���t���u��]�u��}���]É���S�U��$��<����t����эS�$��<����u�$�'L1��1ɉL$�S�M��T$�$��;�É���'U���(�]�E�u��}���t���u��]�u��}���]É��s�$�uL����uR�C1����w-�t$��K�$)�T$�<�pk��9�����K	߉��H�T��D$�$�$>�Dž�u���g�x4�E�t(�|��<$�<�M�Dž�tӋU�1ɉL$�$�4���$�U��T$���u��E�븉�U�����T$�]�1��$� K����t��M�؉�]���]Í�������'U����]��E1ۅ�t���u��؋]���]���$�J��v��'U��E�U��t���t��t�1��
�v]ø����&U��E�U��t3���t-��w(1���t��
�������������]ø(1��䐍t&��鐐�������U����]�u��u�}�������t��v��]�u��}���]Íx,�<$���E��t�S0�M��s0��u�C4��t�<$�,1��1ɉL$�s8�4$�GJ����u��C�S8�C0�$�7J���<$���$��&몍�&��'U����]�u��u�}��)����t��v��]�u��}���]Íx,�<$��U��t�S4�M��s4�K0��u��t�<$�l1��1��D$�s8�4$�I����u��C�S8�C0�$�wI���<$�,�$�&몍�&��'U����]��u��o�Íp,�4$�r��t�{0t1҉T$�S8�$�I����t�4$���]��u���]��C�C0�4$��$�%�ʍv��'U1����(�]�]�u��}��D$�$������t
�]�u��}���]���
�…Ҹt�T$�{,�$�~�E��<$��C4�����K0�����{���U���t3�C�C0�<$���$��$�v��'���o����K�M�$�H�M��1҉T$�$��G��=u��C�U�1��C0�L$�T$�$�pk�@�pk�<$�}�]�$��G��덾�<$�`�{����S��w�K8�$�G����u����
�������������U������u��u�]���(�����(����\$�4$�G����pk�������\$�4$�wG���]�1��u���]Ð��&U����$�#��]Ív��'U����$�#��]���������U����]��(�pk�$�9A����t"�E��t���u�K�(�pk�L$�$�Q@�؋]���]ËK�$��؍�&��'U����]��U�]�M��(�pk�K�$��@�C�]�(�pk�]��U��]��?�U�����T$�]�1��$�pE����t�M�؉�]���]û�됍t&U����]��]�u�1���t���u����]��u���]Ít&�$��D���U��E�U��t���t��t�1��
�v]ø����&U��E�U��t3���t-��w(1���t��
�������������]ø(1��䐍t&������'U���WVS��1ۋu�U������t���t	�8�(�$� ��T$�ED��������H1��@��@�M��|$�t$�$��3����1�1��{�T$�D$�<$�3����1��K�t$�$�r
����u\�$Аpk��D�C�0�pk���C��t�X�0�pk�,�pk��u�,�pk�$Аpk�D���U����e�[^_]Ít&�<$��3�}��<$�3�$1��#C��u���(C�0�܍t&�C�0�ھ(�U���(�]�]�u�1��ۉ}��E��E�t���u��]�u��}���]É�@�N�$Аpk��C�;���w�4$��3��t	�B����W�U�$���E������W9~W�4$�4��u?�]��$���E��$Аpk�C�E������h����E���]������V����0B��M����4$�2��u}�W�$�2��ub�]�$�}����tB9=,�pkt,�W�O�J9=0�pkt�_�S�<$��A�j����0�pk��W�,�pk�W�ϋu�4$�J����A��M���A�0�u��t����4$��3�E������$�pk�B���;�t�E��$�pk�������썶��U1ɉ���U�L$�T$�U�$����]Í�&��'U��U��t]��]�É���'U1҉���T$�U�$����]Ð�t&U�����T$�U�$���]É�U����u��u�]�1��$�pk�A������t)��u��$�pk�A���؋u��]���]Ð�t&�4$1҉T$��������΍�&��'U���X�]�]�}��}�ۉu��E�t���u��]�u��}���]�@���Eą�t��u��3�^�$�(1��u��$�2��t	��?�븉}؍UĹ #pk�U��]؍UȉL$�$�u��E��\$������<$��Eą�t�$������u��i����E��\����M�~�<$�L$��0��u�E����Q?��E���$�pk1��\@������t ��u��$�pk�M@�uă������$1҉T$��������U����}��E�}�]���u�t���u��]�u��}���]�1����t�S�U��$���uڋC��to���tR��t>Љ׉C��U��$�
����t��막|$�K�$�1��t��k>�0��@�J���C�뿋}��]�u��}�}���]���S9~�s�4$�N��u3�C��t	)�C��t��ωK�l������C�_�����=�]��0�$�e�Y���U����}��U�]�u��Z�J�{�M��<$�
��u6�s��t_�N��K�<$�!��uNt,�}��$�
��t����'�M���]�u��}���]Ís�4$�/��t��Z=��֍��SB�����?�Su��K�M�$�S��uЋ�C�U�)���$�[/��u��C�b��������������U��W1�VS��,�E����������P(�$�U���<��������U�u�M�҉p�H���M������J�r�K �J�M�J�����v�C1ɺ����:pk�t$�\$�T$�|$�L$�$�w<�C����t6�E��t	�U�
��uE�4$�=�E�����t�}�E���e�[^_]��E��$1����tۉ<$��;�щ$�U�1ɉL$�T$�$)���P(�U��B�����1��9������������U�����U��t/��r��t��t��]�����l���u����i�ِ������U����]��u��$�pk�u�$�6����t�s�]��E�u���]��4$�];�ސ����������U����u��u�]�1��$��pk�<����t�F��u5��$��pk�<����u
�U��t���؋u��]���]Ít&�$��;��=���u�뷍���U����]�]�u��u�ۉ}�tX��tT�1���t���]�u��}���]ÍS�$�;����t!���uٍt&�$�;�����t�����봿뭐��&U���(�}��$�pk�]�u��$�35����t���]�u��}���]�������ti�H|�@ �3;��<;���E;���.;�$�1҉L$1ɉL$�O�T$�L$�t$�\$�";����t(�_�$�:�G(���|$�5$�pk�4$��3�f����<$�k1��Y����t&U��U9U]������
�������������U���U��x�4�pk1�]Í�&U�4�pk��]Í�U����]������tl�C(1�1��C ��C0�C4�C,�����C$�����L$�T$�D$�$�A:�C8����t	�؋]���]É$1������$���T$�{8�����u������
�������������U����$��pk�]��K9�ppk����t-�S�ppk�C�$��pk�19���؋]���]Ð�t&1��ߍ���U����]��]�}��$��pk����8�1��!�ppk���S�ppk�$��pk��8���]��}���]Í�&��'U���������T$�U�$���]É�U��]�
�v��'U���(�]�U�u���}��U��!����������P0�����H8�}�ɉM�t��v��'�|$�M1҉T$�4$�L$�8��1҅�t��t&1�=��J��������L'�]�Ћu��}���]Ëw�4$�h7����t�s,�4$��{v�4$����C�C0�4$���$���͍}��U�����t&�E��ꐐ�����U���W1�VS���U�u������t���t	�8���$�,�D$�6����tx��������@tc���t]�@�C1�1��C�S�t$�L$�$�%��t%�$�1��5�M����e�[^_]Í�&�S�$�U7����1�뢿�ϸ(�ύ�&��'U����]�]�u�1��ۉ}�t���u��]�u��}���]Ã��w{�E��}��<$�m����u�U��B��tH��B�v�����<$�n����t�}��;��M����$�S%�U����$�6�U����$�4뵐�t&�$��pk��5���;�v��$��pk�5��념�t&������'U�����T$�]�1��$�p4����t��@�M�؉�]���]û�됍�&U����]��E1ۅ�t���u��؋]���]���$��3��v��'U��E�U��t���t��t�1��
�v]ø����&U��E�U��t3���t-��w(1���t��
�������������]ø(1��䐍t&������'U1���U�M��t���t
��w�J�v]ø����&U1҉�E�M��t���t��t�@���]��ú����t&U����u��u�}�1����]�t���u��]�u��}���]Ã��vO�$��pk1���3�����������������������$��pk���3���؅�u���$��3����t.�s��t�Q����D$�S�$������u<�K�$�c��u$�C�s��u��C���E����
������2�8��$�2���{t�$���C�̻�V����$ppk�L$�4$�������>���� ppk�T$��1����t&U���(�u��u�}�1����]�t���u��]�u��}���]Ã��vO�$��pk1��2�����������������������$��pk���w2���؅�u���$�2�������K���(�U����M�s�4$�L$��������~|��t��0�8��&���<����{�}�<$�L'��1���4$�!@t4�$�P1����x�4$��"��u�]�$��1����0�8��$�1���څ�u��v�C�C��u
��C�u����@�����S�U��$�`1���4$�!�����t�M��$�S1�����8���릉$�L'�0���֍t&�����������D$�s�4$������������$�r0���{t
�$������C�������X����$ppk�D$�4$�\������@���� ppk�T$��1�����U����u��E1��]���}�t���u��]�u��}���]Ã�����{t�,����D$�S�$�������tf�{tS�C�{�<$�10���$�/����x�K�$�4!��u�<$�0����t&���|�����.�0���SJ�҉Su�렾�ܾ�Ր�t&U����u��u�}�1����]�t���u��]�u��}���]Ã��wr��t����v�$1ɾ�����t$�L$�<�pk��@t*�{t����0����D$�K�$�������t��C��C�S��u
��C���������$��pk1��/������tM���t=���t#��t�$��pk���/����P������$ppk�T$�4$�s������̸ ppk�D$��1���U����]��]�u�1��$��pk�.������tP���t@���t&��t�$��pk�.�����]��u���]þ�޸$ppk�D$�$��������ɺ ppk�T$��1�����t&U���(�u��u�]��]��tc�۹����t5�M�$�F-����C�U�)ыSi���]�� �����)��xA�L$���$�l-��1҅�t=�t�,�������]��Ћu���]ú�퐐��U��]������&U��]�7�����&U1���U��t�B]��
�������������U���VS���E��tr������@������?B���C�����i������)�4
��������út+�P0��uq�t$�H8�$�,����t=�u1ҍe���[^]Ís,�4$�����{v�4$��������C�C0�4$������$���͉4$��,���������$�,������뉐�t&�@�!������&U��U����$�_	��t�E��E���]Í���'U��S���D�$�pk��1��8�pk��,�P�pk���
�pk�L$�$��,�<�pk�������
8�pk�$(�pk�,�`�pk�������@�pk��uI�`�pk�Ppk�
@�pk��u%1��`�pk�
`�pk��t�
8�pk�؋]��Í��$�X,���΍v�`�pk�4�pk�L$�$�),����t�Ѕ�u��`�pk�Ppk�@�pk뺉$�H�pk�L$��+�@�pk���Y����
P�pk� ?pk�<�pk�$��+��1҉P�pk�����vU���� �pk��u��]Í�&�$�pk�$��$��t�x tQ�s�`�pk��u�P�pk��t��$�y+��봉$�W�pk�L$�S+����t�Ћ`�pk�$�L+��뽉$�?�$�pk1��D$�
�$�9+��댍t&U���]Í�U���� �pk��u��]Í�&�$�pk�$�$��tރx u؉$���$�pk1ɉL$�
�$��*��뵐�t&U�8�pk��M]!�9�����Ð��&U��VS��1��$Аpk�)�,�pk���҉U�t%�u�&�4$�x����M�ËQ�U��t��t��$Аpk�Y)��1������e�[H��^]Ð���U��S��� �pk�����$�pk�����(�pk�����$��pk��(�ppk����t����'�X�$�'����u��$��pk��(���$�pk�s)���$0�pk�d)���$�pk�U)���$Аpk�F)���$��pk�7)���$��pk�()1҃�� �pk�]��É$�� 1ɉ
(�pk�A����$�� 1��$�pk� ����
�������������U��WVS���]��{�s�E��}�u�$��&�M��$�pk�L$�$�F!�E�����<�@�$�/'��tK��t>�������t������}�� t�M��$���$�&����[^_]��j�����u��^�ɋU�$�U�M��ÉA붍���'U�����D$�]�u���}��$�7&����tv������U�P�E�ljC���<$���������uA�u�V�^�<$�S�X����M��t�}�������K�u1���]�u��}���]É$�C����$�%���ߍ�&U��WVS���E��tf��������tV�$�h�����uF�s��t�4$� ��t�N��uJ�C�S��$������t�K��u�s��t�t&���u���[^_]É$�����$��$���$�V뮐��&U1���]É���'U1���U��t���t�:����t���]É���'U���� �pk��t���]Í�&�$$�pk1ҹ�
 �pk�T$���u�$(�pk1��D$���t�D����$��pk�&���$��pk�	&���$Аpk��%���$�pk��%���$0�pk��%���$�pk��%� �pk���U���U����]�U�u��}������u��X����߃�,�4$�����M�A�4$�+����E�$������u�!�U�$�����E���uS�U���|����$�����<$�
�����\�����t�]Ԁ���t��t&�]�u��}���]É$�k%���捶�$�X%��렍vU����]��]��t�S��u	�S��t	���]���]É$�����]�]���]��"�vU����E��t������L$���$�n#��1҅�t�"���������]��
�������������U��WVS���$�pk�}�$��W��Ã�wJ��t�H|����t1���t/��t#�L����4$�"�t&�$�$�����u��������֋s���$�"���|$�s<�4$�a"�U��S���]���$�������u�Y[]�U��M�U�E��]�����U��S��1��2#�$�M��L$�M�L$��#����t*�U�1ɸ�t&��'��tA�u��U�
�؋]��û�򐐐�U�����U�]�]�u�1��ۉ}�����t
������$���T$�4!����t^�@1��@�@�\$�$��������uY1ɍ~�L$�<$��������u:1ۍV�\$�$�M�������u�F⭬�}�؉7�]�u��}���]É<$�4����4$�,����4$1��r �л�ɉ���'U���(�u��u�}�1����]��E��E�������������{⭬���$������t�v��'�]�u��}���]ÍS�U�$���������uX�C��~1�M�$�]����$���S����E��E�����u��E���u��E�맋S9S��C�}�<$��������t�$�������x����$�������h�����S�$�W����u�lj4$������E��$������E�$�4�v�����%����$0�pk�I ���>�t��$0�pk�@ ���?������U�����T$�]�1��$�����t��M�؉�]���]Í�������'U����]��E1ۅ�t���u��؋]���]���$�l��v��'U��E�U��t���t��t�1��
�v]ø����&U��E�U��t3���t-��w(1���t��
�������������]ø(1��䐍t&������'U����}��}�]�u����������������{⭬���$������uj�SB������St�]�u��]�}���]�����{�<$�|�������u �K�C�C)��K�<$���������t��$������������]�u��}���]Ív����$0�pk1��;������t*��u��$0�pk�,����t����u���$����<$1��D$�y������͐�t&U����u��U�u�]�}����U��������������{⭬���M��$�L$�������uM�sF������st�]�u��]�}���]������}��s�4$�|$��������t$=L't�$��������]�u��}���]��C��S�C�C)‰S�4$��������t�������$0�pk1��������t*��u��$0�pk������t����u�������4$1҉T$�E������͐U���H�}��}�]�u����������������{⭬���$�^�����t�v��'�]�u��}���]Ív�S�Uԉ$�2����������K��uw�C��~
)C�C�C��~_�ؿLpk�u؉C�|$�{�\$�4$�9�������'�<$�UԉT$��������u�K��x�1҅��‰$������u�C��u�C�v���I����$�������5����$0�pk1��������t.��u��$0�pk�����t����������������<$1҉T$��������ɍ���'U���H�}��}�]�u���������������{⭬���$�U�T$������t�v�]�u��}���]Ív�u�K�Mԉ$�t$������������C��uw�C��~
)C�C�C��~_�عLpk�}؉C�<$�{�\$�L$�������<$�u�Uԉt$�T$�:�������u�K��x�1҅��‰$������u�C��u�C�������9����$�������%����$0�pk1��������t.��u��$0�pk������t���������������<$1��D$�A������ɍ���'U����]�E�u��}����������1����tE�{⭬ur�C��uU�{�<$�J�������u$�SB�҉St&�<$�������‰�u	�Ѝ�&�]�u��}���]ÍS�$�������ˍt&H�K�C�$�q����$��봸�ÍvU����}��}�]�u����������������{⭬���$�������uj�SB������St�]�u��]�}���]������{�<$�l�������u �K�C�C)��K�<$���������t��$�����������]�u��}���]Ív����$0�pk1��+������t*��u��$0�pk�����t����u���$����<$1҉T$�i������͐�t&U����}��}�]�u����������������{⭬���$�������t�v��'�]�u��}���]Ív�{�<$��������uW�S��u@�C��~
)C�C�K��~/�<$��������t�$������릉$��������u����C�މ$�p������x����̍���f����$0�pk1���������t.��u��$0�pk������t�����'����������<$1҉T$�"������ɍ�&��'U����u��u�]�1��$0�pk�s������t)��u��$0�pk�d���؋u��]���]Ð�t&�4$1҉T$�������΍�&��'U����]��]�S�C�ډS�S�$�Z����]�]���]�L���������������U����U�$��������u
1҃}��J��0���]ÍvU����]��U�]�$������u��t���v�1��]���]ø��U����}��}�u��u�]�<$�S�����u&��t"��$�9�|�$�}9�~��]�u��}���]Í�&�1���Q�ᐍt&U����]��]�u��u�$�������u��t�1��Q��]��u���]ø��t&U����]��]�u��u�$�������u��w��r1ҋ]��Ћu���]Ð�t&U����]��]�u��u�$�f�����u��t�1��Q��]��u���]ø��t&U1҉���u��u�]�]�}��}�T$�4$�������u6���w,�۸0u#��u�]��E�u��}��U��]����]�u��}���]ÍvU����u��u�]�]�}��4$���19�|�4$��9�~��]�u��}���]Ã��~]���}X������U��$�U��$�O�������t	���ɐ�t&�|$�E�H�$�~����u��]��$�����̋}�_(��S���w��랍�&��'U1�����]�]�u��u�}��}�D$�$������u��v!��t�1��S(��]�u��}���]Ív������'U����}w	���]��v�����������'U����}w	�������]��F�����������'U����]��]��u"�]1���u�]���]���(��������Y9�tՉ\$1��D$�$�O����u������L�����ʍT	�붍t&��'U����]��]��u1��]���]Í�&��9�t�\$1҉T$�$������u��e��������������ʍT	�몐��&U����$���1���]Ð����U����]��E�u���t���������]��u���]É��$���D$������t��$�U1ۉ\$����?�L$�T$�>�����t	�U1��2렉4$��녍���'U����]��]�u���t���u�b��0������]��u���]����Ɖ$�j����u�3�ȉ4$�1��͍vU����]��E��t���u���������]��Љ�]�1ɉL$��$���1�=uۻ�ȍ���'U����]��E��t���u���������]���]É���$������1���t��׍���U���(�u��E�u�]����tw�������tL�H����C�� �i������ӍU�$�t�M�U�i���1�9�v��)у��t6���L$���$������1���u
�]��u���]���
�������������ɉ���'U����]��E��t���u�
��������]��Љ�]�1ɺ�L$�T$��$���1҅�u�����U����]��E�U��t-���t'��~#�T$1ۉ\$��$����1҅�u���
��������]��Љ�]Í�U����u��E�u�]���tz���tt��tp1҉T$��$�
��=tF�M���L$�T$��$�L�E���]�1���
��������������]��u���]Í��E��э�&�k�������΍�&��'U����E�(������]Í�U����%�(������]Í�U�����(������]Ð�����U���WV1�S���M�E���t_�U��$������t�E��}�~�}�(t8�$��L$��Å۸t�E���~�C��}�����[^_]Í}�<$���������t�<$�2�����tԉ$�6�]��ƋM�s�E��4$�|$���������u��뼍�U����u��u�}�1����]�t���u��]�u��}���]Ã��tM�;t9�$1���T$�D$�<�pk��Ht	���u��$�
��밍S�$�2��������$�pk����>�t��$�pk�������獶��U��VS���u��tS���tM���tT���$���L$�T$�<�pk����t݋1���t��u�s�u�e�[^]�������e�[^]��$�pk1���
������t%��u��$�pk��
���؅�uË�u����4$1҉T$�������ҍvU����]��E��t@���t:����t5�$��T$��T$�<�pk����t1��H�t��]��Љ�]Ã�u�K�]��M��]����1��ݐ��&U����u��u�]���t=���t7���tc�$���T$�D$�<�pk����t9��1�Ht
��t&��]��Ћu���]Ã�u�K�u��]��M��]���������$�pk1��	������t%��u��$�pk�	���څ�u���`����4$1��D$�T�������U����u��u�]�1��$�pk�C	������t)��u��$�pk�4	���؋u��]���]Ð�t&�4$1҉T$��������ΐ�������������U1҉���]��]�T$�$������u
�{ t�C �]���]ø��&U1�����u��u�}��}�]�D$�4$�]�����t
�]�u��}���]��G����…Ҹt�t$�$�$�������uG�~ tL�V�$��������u4��t�|$�N�$�	����t�4$������&��'��냻����������������U�����T$�]�u�1��}��}�$������tA�\	�@t"��t
�C�����{�U����]�u��}���]É$�1��V�ۍt&��Љ���'U����}��}�]�u���t*�G��t�G��u<�7�4$���_����u�<$��]�1��u��}���]Ð�W�$�����ۍv�W�U��$�������u��w��t��&�4$�������t��u��M��$�5���뇍v�F�^�F�4$�����4$���m����Ǎt&��'U��WVS���];$�pk�}���P������ts1���tk��tM�K��tF��tB����҉U�t�эv9Zt	�R�҉�u�M���u�\$�U��D$�$���������u���|$��$�����u���e��[^_]É$����s������l����vU����]�u��}��,���E�M�Nj�$�v���É4$�y���<$�.���؋u��]�}���]Ð������������%4�pk���%8�pk��U����0ppk���u��]���0ppk�B�R�0ppk��u����U����]��@dpk���t)����u�$�\pk�����]���]Ít&��@dpkKu��݋Ddpk1���t˺@dpk�v@�\���u�븐�t&U�4ppk���t]É�]��
4ppk낐�U��V�MS�]�u9�s ��&��'�A��‹��9�r�[^]Ív��'U����D$pk�D$��pk�$��pk������]Ð���������U����`�pk�P��]Í�&��'U1��������$�]�|$����8�p�pk�Tppk�C�apk�C�Pppk�S�C,�����C���pk�C�]pk�C$�C(�Xppk�\ppk�C0�S4�$�|$��]Ð�t&U���X�]��`�pk�u���t�]��u���]Ð�E�AAAA�l�pk�u��E�AAAA�E�AAAA�Eءp�pk�E�AAAA�E�AAAA�Eܡt�pk�E�AAAA�E�AAAA�E�x�pk�E�AAAA�4$�E�|�pk�E血�pk�E졄�pk�E𡈀pk�E�������f��ub�$8������t\�$�����$�`f��t�`�pk�C�P�pk�C�p�pk�%����$�x�4$������v��'�$��������
�������������U���V�S��P�u�t&��'��Au�a�L��Hy�l�pk�Eءp�pk�Eܡt�pk�E�x�pk�E�|�pk�E血�pk�E졄�pk�E𡈀pk�E�E��$���؃�f��u1ҍe���[^]É$�9���u��獴&��'U�@��S��T1��E�T$�U��T$�$�����t0���v��'�|�At�Hy�;8u�؋]���	���������������������%��pk���%�pk���% �pk���%�pk���%(�pk���%�pk���%��pk���%�pk���%�pk���%$�pk���%�pk���%�pk���%�pk���%��pk���%�pk���%��pk���%Աpk���%��pk���%��pk���%��pk���%ȱpk���%d�pk���%��pk���%��pk���%��pk���%бpk���%��pk���%t�pk���%|�pk���%`�pk���%T�pk���%�pk���%��pk���%\�pk���%��pk���%��pk���%l�pk���%�pk���%P�pk���%��pk���%̱pk���%x�pk���%��pk���%��pk���%X�pk���%��pk���%��pk���%رpk���%ܱpk���%�pk���%ıpk���%h�pk���%L�pk���%p�pk��U��]�'��������������0dpk����ppkppkPdpk��������KERNEL32.DLLInterlockedCompareExchangeQUSEREX.DLLQueueUserAPCEx_InitQueueUserAPCExQueueUserAPCEx_Fini-LIBGCCW32-EH-SJLJ-GTHR-MINGW32D{jA��ss(������)�)��M MpL0��p``M�L@LP�`��0p���0 �� ����@$�40Y�'�%(O@\�4pY0Z�Z�%�+�*.@/P2�1�,�4 -�-�,�4P-�-�5p&�@�?C0D�F I@JpH`EPB�BB�B�&���'�M�[�UU�V�WpWp�86@7`8�78<�PpO�OPP�O�P�T�QT�P�T@S�S�R�Q�T@R��Ϥ����3�N�j�������ƥ����6�L�f�������¦ަ���5�D�[�p���������ا��
�&�5�F�U�c�p�������Ϩܨ���%�8�K�c�y�����ũ����0�M�g���������Ϫ���7�M�c�~�����ҫ߫���#�9�M�b�t�������¬�� �?�^�}�����ĭۭ���$�.�:�G�P�Y�b�t�������	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrpthreadGC.dllpthreadCancelableTimedWaitpthreadCancelableWaitpthread_attr_destroypthread_attr_getdetachstatepthread_attr_getinheritschedpthread_attr_getschedparampthread_attr_getschedpolicypthread_attr_getscopepthread_attr_getstackaddrpthread_attr_getstacksizepthread_attr_initpthread_attr_setdetachstatepthread_attr_setinheritschedpthread_attr_setschedparampthread_attr_setschedpolicypthread_attr_setscopepthread_attr_setstackaddrpthread_attr_setstacksizepthread_barrier_destroypthread_barrier_initpthread_barrier_waitpthread_barrierattr_destroypthread_barrierattr_getpsharedpthread_barrierattr_initpthread_barrierattr_setpsharedpthread_cancelpthread_cond_broadcastpthread_cond_destroypthread_cond_initpthread_cond_signalpthread_cond_timedwaitpthread_cond_waitpthread_condattr_destroypthread_condattr_getpsharedpthread_condattr_initpthread_condattr_setpsharedpthread_createpthread_delay_nppthread_detachpthread_equalpthread_exitpthread_getconcurrencypthread_getschedparampthread_getspecificpthread_getw32threadhandle_nppthread_joinpthread_key_createpthread_key_deletepthread_killpthread_mutex_destroypthread_mutex_initpthread_mutex_lockpthread_mutex_timedlockpthread_mutex_trylockpthread_mutex_unlockpthread_mutexattr_destroypthread_mutexattr_getkind_nppthread_mutexattr_getpsharedpthread_mutexattr_gettypepthread_mutexattr_initpthread_mutexattr_setkind_nppthread_mutexattr_setpsharedpthread_mutexattr_settypepthread_num_processors_nppthread_oncepthread_rwlock_destroypthread_rwlock_initpthread_rwlock_rdlockpthread_rwlock_timedrdlockpthread_rwlock_timedwrlockpthread_rwlock_tryrdlockpthread_rwlock_trywrlockpthread_rwlock_unlockpthread_rwlock_wrlockpthread_rwlockattr_destroypthread_rwlockattr_getpsharedpthread_rwlockattr_initpthread_rwlockattr_setpsharedpthread_selfpthread_setcancelstatepthread_setcanceltypepthread_setconcurrencypthread_setschedparampthread_setspecificpthread_spin_destroypthread_spin_initpthread_spin_lockpthread_spin_trylockpthread_spin_unlockpthread_testcancelpthread_timechange_handler_nppthread_win32_process_attach_nppthread_win32_process_detach_nppthread_win32_test_features_nppthread_win32_thread_attach_nppthread_win32_thread_detach_npptw32_get_exception_services_codeptw32_pop_cleanupptw32_push_cleanupsched_get_priority_maxsched_get_priority_minsched_getschedulersched_setschedulersched_yieldsem_closesem_destroysem_getvaluesem_initsem_opensem_postsem_post_multiplesem_timedwaitsem_trywaitsem_unlinksem_waitT���L������<��4�@�L�\�l�������IJв����0�H�\�l�������ij����(�8�H�\�l�|���������ȴش����,�D�T�h�x�������������ĵ̵ص���@�L�\�l�������IJв����0�H�\�l�������ij����(�8�H�\�l�|���������ȴش����,�D�T�h�x�������������ĵ̵ص���AddAtomACloseHandle3CreateEventAICreateSemaphoreAWDeleteCriticalSectioncDuplicateHandlefEnterCriticalSection�FindAtomA�FreeLibrary�GetAtomNameA�GetCurrentProcess�GetCurrentProcessId�GetCurrentThread�GetCurrentThreadIdGetExitCodeThreadGetLastErrorCGetProcAddressDGetProcessAffinityMaskoGetThreadContextqGetThreadPriority�InitializeCriticalSection�InterlockedDecrement�InterlockedIncrement�LeaveCriticalSection�LoadLibraryA�OpenProcess3ReleaseSemaphore8ResetEvent9ResumeThreadnSetEventzSetLastError�SetThreadContext�SetThreadPriority�Sleep�SuspendThread�TlsAlloc�TlsFree�TlsGetValue�TlsSetValue�WaitForMultipleObjects�WaitForSingleObject$__dllonexitr_beginthreadex�_endthreadex�_errno�_ftimeq_setjmp�abort
callocexitfflush(freeZlongjmp[mallocWSAGetLastErrorWSASetLastError�����������������������������������������KERNEL32.dll�������������msvcrt.dll(�(�WSOCK32.DLLL90p00�0�0�0�0
11:1E1U5�9�9�:�:;f;};W=h={=�=�=�=:>�>??7?B?�?�? Dd0�0:1�1�1�4�56#6�6�7�78�8�8�8�829I9U9\9S<m<8>n>?.?x?�?0�T1l1�2�2 3=3R3t3�3�3�366"6*6;6L6T6^6o6x6}6�6�6�6�6�6�6�6�6�6�6777!747H7b7~7�7�7�7�78"8B8c8�8�8�8�899!9+9U9d9s9�9�9�9�9�9�9�9*:X<s<�<�<�<�<�<�<�<�<={>@,�1�1�3�35/5�5~6�6�78/8�9:-;N;�;�;Pt>6u6�6�6!7B7�7%8t8�8�8�8�;�<�<�<�<�<�<=#=.=9=R=h=�=�=�=�=#>)>0>8>J>Q>`>f>�>�>�>�>�>�>???W?_?g?�?�?�?�?`�0
000�0�0�011"121B1R1b1r1�1�1�1�1�1�1�1�122"222B2R2b2r2�2�2�2�2�2�2�2�233"323B3R3b3r3�3�3�3�3�3�3�3�344"4D4p 0$000

deps/Windows-deps/x86_64/DLLs/pthreadGC_64.dll

MZ����@���	�!�L�!This program cannot be run in DOS mode.

$PEd���nR�."�B �g�/ 0�@���
p8`(C�.text�� P`.data���@P�.rdata���@`@.pdata�
��@0@.xdata�	
�@0@.bss0�`�.edata�0�@0@.idata�@�@0�.CRTXP�@@�.tlsH`�@`�.reloc8p�@0BSH�� ��!�H��H���SH��H��H��t1�H�H�� [�@�H�� [�DATUWVSH�� ��H��M��u}������>������1��H�u1�H��H��3�tf�����H���H�=MH��u�:������g��H�� [^_]A\��u�eH�%0H�p1��H�5�H��t9H9��0H�@31��
@H9������H���H�5�H��u�1ۋ���� �������������u
1��H��H���H��t
M��H���Ѓc��H�� [^_]A\�1�����f�H�
!��QH��H��tIH�
��QH��H��H9�wH�H��t�H����H9�v�H���9�H��H����1��H���H�� [^_]A\û�����DH��=H�
�=���ۮ������輮�����H��=H�
q=贮�Z�����ffff.�UWVSH��(��H�ω�L�ʼnl�uF�0���t^�SI��1�H����ƃ����������/�����H��([^_]�f��KS�C���w1I���H���&�������1���f.������VI���H���%����u���u�1�I��H���
1�I��H��� c1�I��H����������[���f.�I���H����bI���H�����������D��.���DI���H����b�����Y������B���I��1�H���S��������I��H���n��������H��H�R���t
H��H�t���@�T$0H�L$8L�D$(�U�8YL�D$(H�L$8�T$0H��H�A����SH�� �H��H��tF�(褬H�¸H��t/H�B�B0��B�B �B$�����H�H�� [�f�SH�� H���#+���t
��H�� [�f�H���B�1�H���H�� [ÐVSH��(H��H����*����t�ЉH��([^�fDH��t�H�0ҋH�ЉH��([^��VSH��(H�ˉ��*���t	��H��([^Ã�w�H�0ɉp��ffffff.��(�f.��(�f.�VSH��(H��H���/*���t	��H��([^�H�0�H�@H���H��([^��VSH��(H��H����)���t	��H��([^�H�0�H�p��H��([^�ff.�H��@$�1��D����t
���t��H��@$1�Ð�������������WVSH��0E��H��H��u�H��0[^_ÐH��t� �D�D$(藪H��D�D$(�H��t�H��t`H�H��tX�H�_D�GD�E1��W�GH����?��tH���:��H��0[^_ËWH�OE1��?��uH�>�i���f�1��H���4@��f�UWVSH��(�H��H��t$H�9H��tH�oH�H���@����tH�;��H��([^_]�H�O��?����t�WE1�H���??��H��蕩D��fffff.�WVSH��0�H��t7H�H��t/�{���������t(���xTtkHc�H�L��.@�ƅ�t(��H��0[^_ËS���vHcǃ�H�L��TA���ԺH�KA��)�1����9�@�ƃ���H��0[^_��H�T$ ��!��u�Hc�H�L��?�L$ 1҉���r���fffff.�SH�� �H�˹虨H�¸H��t�0�H�H�� [�ff.�H��(�H��tH�H��tH�H���;�1�H��(�@�H��tH�	H��tH��t��1��Ð�H��t
H�	H��t��v	����(��D�Ð����������������f,fD��V,fDUWVSH��(��H���H��H��u�H��([^_]����w�H�hHH����H��t�CP����sPu�CT��tH���_1�H��([^_]�@1�H�KX��*��u�H�KX�C�CP��)H��� ��+�@UWVSH��(��H���^H��H��u�H��([^_]����w�H�hHH���/H��t�CT��sTsPtH���1�H��([^_]�f.�1�H�KX��)��u�H�KX�C�CP�()H���p���*�@VSH��(�H�pHH��H���H��t�{Pt1�H�KX��)��tH��H��([^�H���C�CP���*H��H��([^��ffffff.�SH���H���D$PH�T$ H���(H�����H�T$ H��H��$��(1�H���[��UWVSH��(1�H���N����t��H��([^_]���H����H�~HH��H���H�����H�~Pt"�~���H���(��H��([^_]Ã~w��usH�nH���(1�H���[(=�x���E1�H���F�FPH�
�������H����H���v'�A���f����H��([^_]�H���F�FP���)����H�NX�Q'���D��2�����VSH��(��H�
9���CH��H��t"��tH�H��tH�K��H�SH�
��DH��H��([^��SH�� H��H�L�AH�
���CH�
��H��H�CH�� [�C�������������ATUWVSH�� H�YL�aH��H�{ H�����u+�k��u4�C��=���?�CttH�����t/�A�$H�� [^_]A\Ð�E�H���C�b��uރ�tH����u�H�� [^_]A\�f�H�K�;��t���&��f�H�kH���4'��u݋C)H����:��u��C�_���SH�� �H�˹�٢H��H�҃���H�� [�DSH�� �H��H��tH�	H��t葢H�1�H�� [�f��H��tH�	H��tH��t��1��Ð�H��t
H�	H��t��v	����(��D��ffffff.�ATUWVSH�� �H��H��tyH��tH�H��t	�8��8����H��H����H�h1���@�@A�H���P7��t,�^%�0H��1�蚡��tDH���H�� [^_]A\�L�cE1�1�L���7����H�K 1��\������H�
K�E#H�&�H�C(H��H�C0tH�X(H�=�H��tMH�
1���#H��q�����1�H��a�����(1������$�0H���7�'���H����f�L����6��fDSH�� H��H�
a��"H�H���t"H��ۃ�H�
B�#��H�� [�@H��1��F�������f�ATUWVSH�� �H��H����H�H����H�����H�
(�""H�;H�oH���7���L�g L���������
�G9��H�H���6����H�O1���5���L����������H9=���H�W(H�G0H�P(H9=v���H�W0H�G(H�P0H���t�H�
m��!��u�ۉ�D���H�� [^_]A\�H���77��usL���F���f�H�
���!H�;���H�
�1�1���!뚐��"�0��H�� [^_]A\�H����6념��"�0������"�0�fDL������������b"������H�G0H�}�����H�G(H�u������H�@0��]����WVSH�Ā�H��H��H���D$0��H�1H����H�����H�^H���5��uw�H���6��uhH�D$0L�D$`H�G���H�L$@H�|$`H�t$hH�D$p�D$x�����H�������D$0tv��������D$x�p����D$0H��[^_�@�b!�H��[^_ÉD$(H�
U��H��D$(H���teH��t5H�
6���D$0H�3�)���H�N1��4��u#�D$0�r����D$(H�
�����D$(�r����� ��D$0�G���1�H�������H�
���D$(���D$(������D$0�3����ffff.�UWVSH���M��H��H��L����H���D$0��H�9H����H�����H�wH���{3��uw�H���l4��uhH�D$0L�D$`H�����H�L$@H�l$`H�|$hH�D$p�D$x�F���H���N���D$0tv��������D$x������D$0H�Ĉ[^_]������D$(H�
����H��D$(H���tlH��t<H�
���^�D$0H�>�/���fDH�OH����2��u#�D$0�q����D$(H�
\���D$(�q����?��D$0�F���1�H���R���H�
+��D$(���D$(������D$0�2����{���f�WVSH�� H��tTH�H��tLH�����H�{ H���
����u&�C��t9���ts�����C�H�������tj��H�� [^_þ��H�� [^_Ð�C9~9H�K����u\�C��t	)�C�C�+�1���H�� [^_�@H��H�� [^_��H�K��2��t�� �0�w�����H���0�`�a���ff.�UWVSH��(H��tUH�H��tMH�����H�{ H�������u&�C��t:�+��tr���CH��������ti��H��([^_]þ��H��([^_]ËC9~7H�K����uZ�C�+��t	)��C�k��1���H��([^_]�H��H��([^_]�H�K���1��t��#�0�{���@�H���0�`�b��������������AVAUATUWVSH��0H��H��M��M���!H��H�����D�p@���H��H����H��H�L�hL�`��H�H����L�`�PD�p�@ �S4����D���CHǃh1�H�\$(�D$ I��L��6H��I��H�C��H�?t
E��1�H���[+L���*1��H��1��$�H�]H��0[^_]A\A]A^��D�p@�l���1��h����CHǃh1�1�H�\$(�D$ I��L�z��H��I��H�C�y���H��1��H���җ��y�����������H��(��t7r��t@��t�H��(Ð�[�H��(��H��(�G�H��(�'�H��(��������SH�� H��H�
Q���6H��t�H�X H�� [������������������VSH��(H�ˉ�H�
���H��t4H�KH��t+�\=���tH�
f��h����Ѓ�H��([^�H�
H��J�H��([^�fDVSH��(H��H��u�H��([^�fDH��t�	��u/���C���t)�H�5���uf�1��֋��t�1�H��([^����1���1�H9��������x�
�0���ffff.�����f�UWVSH��(H�
q�H�5���H���H��twH�CH�
P�H�CH�-IH�z���E1�E1�1��C@�C4��CP�CTH�CH����H�C8�����YH��H�CXt5H��H��([^_]�H�
��H�-��պp��U�H��H��t��H�
��H�������puz@��uf@��uQ��1������H�t
�H����t	f�H����t�H���H�
\�H���H�C1����X������H���f���H����H�{�o�x���ffff.�ATUWVSH��@H�
��*4H��H��tH��H��@[^_]A\�@�[���H��H��ti��`�@4�gH�=H���I���KH�����D$0�D$(L�N�D$ M��H��H������t$H�N�U�F@H�
��H��H����3�a���H�
L�H����@���pu|@��uh@��uS��1������H�t
�H����t	f�H����t�H�6�H�
��H�5(�H�F����������H���f���H����H�~�o�v���fffff.�SH�� H�
���H�ǡH��t1H�CH�CH���H�
g��iH��H�� [��1���fff.�WSH��(H��H�
0�����H�ߺpum@��uw@������1������H�t
�H����t	f�H����t�H��H�
��H�	�H�CH��H��([_H��DH�{��o@��t��f�H����@���}���f.����H���a���fffff.�VSH��8H�L$ �@���H��H����D�@PE��t?�E1�H�T$ A������
1҅�t��t7=���EЉ�H��8[^�H�@X�H��H�D$(u���H�L$(�H�ۺt�H�sHH����{vH���A���H��8[^�H���C�CP�����H�D$(�5���VSH��8��H�L$ �N���H��H����D�HPE��t<�E1�H�T$ A���1҅�t��t8=���EЉ�H��8[^�H�@X�H��H�D$(u���H�L$(�%H�ۺt�H�sHH����{vH���Q���H��8[^�H���C�CP�*����H�D$(�7���WVSH�� �H��H��H��twH��tH�H��t�:�(tc�H��֏H��H��trH��������@t\H�H��tT�@H�KE1�1҉CH�C�(%��t$H��1��z��H�H�� [^_�f.�H�K ��1���f�1�뫸��DSH�� H��H�
���+H�H���t2H���t<H���tIH��ۃ�H�
������H�� [��H��1����������f�H���H�����������H���H���������f.�SH�� �H�˹詎H�¸H��t��B0�H�H�� [�@H��(�H��tH�H��tH�H���K�1�H��(�@�H��tH�	H��tH��t��1��Ð�H��t
H�	H��t��v	����(��D��ffffff.��H��t
H�	H��t��v	����Q0��f.��H��tH�	H��tH��t�A�1���VSH��8�H��H��tPH�H��tHH���w������tN�K��t:�����H�KH���	�����t%��������{�$��H��8[^�fDH�K�G��us�S�C���upH�C1�H��8[^��D$(H�
e���H��D$(H���t|H�����H�����H��tIH�
2��4H��5���@�R��f���������f��C0��H���D�D$(H�
�����D$(�)���1�H���L����D$(H�
�����D$(������H������H��H��������H���H�������fffff.�WVSH��@H��H��H���H�H���H������������D�SE����H����H�L$0H�s�MH�H+T$0���CDi���W�� ������D$8��D�)���H�CH�������=��H�{ H���,
H���!������|H����
1���uOf.�D�K�C�E���@H�C1�H��@[^_�f�H�
I��K
�H��@[^_�H�
)���H�H����<H����aH����hH��t�H�
����H������H�{ H���SH���� ��������������~H���"������D$(H�����D$(�O���f.��k���H�KH���������B�����������{�$�����C0��	���@D�C�C�E�����������������3H����������fD�����R���H�#
����Ӌ����1�H���P����D$(H�
�����D$(���x���H��g���H���H��������H��H����������������ff.�VSH��8�H��t0H�H��t(H���w"H�{t+�6���H�KH���z�����u�@H��8[^�f��{u�kuIH�s H�CH���
���������~
H�K�Y ��u%1��D$(H����
�D$(H��8[^�1��������fDVSH��8�H��H��t=H�1H��t5H���w?1�A�����H��������ty�~���f.�H��8[^�f��D$(H�
E���	H��D$(H�����H�����H�����H��t5H�
��
H�3�q���D�^�F�E��uIH�F1���D$(H�
����	�D$(�f�������H�NH����������>����F1��B��������1�H�������D$(H�
����	�D$(H�3�����������H���H���������H���H��������f.�VSH��8�H��H��t=H�H��t5H���w?H�L$ H�D$ �`�������uH�D$ �P��t]����Pf���H��8[^��H�
����NH�;�v
H�@0�H�
������H��8[^��H�L$ H���������t
H�D$ H��H�L$ H���!H�L$ H�� ��H�L$ �؅�c�����������ff.�����ff.�H��tH�A�fD1��ffff.�WVSH�� H��t`H�1�yH��u��tw�����H�øH��tD��?B���C������CPi����)���u-H�KX����tO=���H�� [^_����� 1�H�� [^_�����1��	����1�H�� [^_�f�H�sHH���D����{w H���C�CP�������N	H�������H�� [^_�f�f1��i����H��8H�L$ �	���DT$ ��H��8�ffffff.�WVSH�� �4H�
������H�5���H��H��H�'�H�X��H��H������
��H�
آ��H��H����H��H�Ȣ��H�
��H���H��t_H�����H��t�Ѕ�u0H�����H�
��H�f���H�����H�� [^_�H�=��t�
J���H�� [^_�H�����H��H��t�O��H�Z�H�� [^_�f�H���1��^���f�H�9H�
"�H����
H�
������DH��(�����u�H��(��H�
���t"H��t�x4tN�H�
��H��t!H�����H��t��H�
����H�
��H��t��}�H��(�H���3H�\�1ҋ��뗸�f.�H��(�
>���u�H��(��H�
���!H��t݃x4u�H����H���1ҋ�8�fffff.����!�9������ffffff.�H��HH�
����H���H��H�D$0u�DH��tH�L$0�M���H�T$0��H�R(H�T$0t߉D$(H�
p����D$(��t�H��H�H�
Q���1�H��H���H��tH�H��t�8���������fD��f.�SH�� �
����tH�� [�fDH�
��1�����H����������H�
��H��t�H���H�
��H��t�H���H�
��}H�
6�H��tH�Y�g�H��H��u�H�
����H�:H�
����H�
z���H�
����H�
(���H�
����H�
������H�{H�
|���H�
s���H�
����H�
����H�
���H�
��Ӌ��H�� [ÐH�
��1��"���������SH�� �
������H�
��H��t�lH�q�H�
b�H��t�PH�M�H�
���HH�
�H��tH�Y�2H��H��u�H�
����H�H�
N���H�
E���H�
����H�
����H�
j���H�
a������H�� [�ffffff.�AUATUWVSH��(�I��H�չ�(L���~H��H��tPL�gH�����H�hH�xL�����������u>H�GL��H�_H�C �j���H��tH��hH�CH��hI�]��H��([^_]A\A]�H���h���H��� ~��H��([^_]A\A]ÐSH�� H��H��tH�ytH�� [�fDH�yu��$���H��H�� [��}�WVSH�� H��H���}H��hH��tq�H��������u�H�{H��tH���CH��tH�WH��tH����H�CH�CH��H��h�u���H�{u�H�{u�H������H���G}�DH�� [^_��UWVSH��H��H��ttH�iHH��H���~���H���CH�l$ �
���H��H�������.�H�H������H�L$xH��t���H�MH����H�M8�����H�L$(H��t
��$�tH�Ę[^_]��o��H�Ę[^_]�f.�SH��@H�H�QH�D$(H�AH�T$0H�D$8�\|H�T$(H�
P��;H�T$(�B�1H�L$(H��H��`�a|��t2��tH�D$(H����x4t8H���9��������H�T$(H�Z H����H�L$8H�T$0��H��H�D$(H�X ��������f�H��(H��tH������H��&���uH��(��_���������f.�SH�� ��f����)���H��u�H�� [�fffff.�VSH��8��H�
Q����S���v
��z{H��t	��`t�����t�p �����������H�D$(�u���H�D$(��H�H`�k0�@1��ffff.�1��ffff.�SH��@H�����H�T$ L�D$0H��������u��H��@[�L�T$ A�@1��D�HL��AE�H�A��u�1҉��H��@[Ð�����������SH�� �A H���A �؉AH�I�P���H��H�� [�C���UWVSH��(�H��H��tH��t1�H�:tH�;��H��([^_]ú(����yH��H��t�1��@�@�@ H�����������u>H�o1�H����������u"H�O1���������u	�G$⭬�H�������H�������H��1��wy�d���f�SH�� H��H�
���[�H�H���t"H��ۃ�H�
�������H�� [�@H��1����������f�UWVSH��(�H��H��tH�1H��tH���tr�~$⭬t��H��([^_]�f�H���H�������u�H�nH���6�������ul�F���F 9F~jH������H��������Å�u��ۉ�D��H�
����y�H�;�tH�
��1�1������H�@0���H���\����S���H���F$�H�������H��uB�:��������,���H�NH�����H����F���H����<���H�����w�U��������������ff.�SH�� �H�˹��wH�¸H��t�0�H�H�� [�ff.�H��(�H��tH�H��tH�H���kw1�H��(�@�H��tH�	H��tH��t��1��Ð�H��t
H�	H��t��v	����(��D��ffffff.�WVSH�� H��H��tH�9H��tH���tE�$⭬t���H�� [^_�H���3�������u�G��=����GtKH��H�� [^_����H�
�����H�H���t`H��tH�
�����H�>�H�
������H�wH�����������u�G )GH���G �K�������t�H���=����S���1�H���������H�
U�����������.���닐UWVSH��(H��H��H��tH�9H��tH���tP�$⭬t���H��([^_]�fDH��H�����������uދG��=����GtOH��H��([^_]����H�
�����H�H���twH��tH�
�����H�>�H�
������z���H�wH��H���Q�������t=�u�G H���8����R����G )GH���G ���������e�����1�H���������H�
/��q������������q����ATUWVSH��@H��H��tH�9H��tH������$⭬t���H��@[^_]A\ÐH�����������u�H�wH��������������G��ud�O �W��~)��G �W��~J��H�L$ L�g�W H�����I���.���H��L�������������W ��x�1������G�G���G�X���fDH�
)����H�H���t9H��tH�
��P�H�>����H�
���;�����H����������1�H���g�����H�
���������������벹�����������f�AUATUWVSH��HH��H��H��tH�9H��tH������$⭬t���H��H[^_]A\A]�f.�H��H����������u�H�wH��H�������������G��uh�O �W��~)��G �W��~N��H�L$ L�o�W H�P���I������I��H��L��������A�����O ��x�1��1����G�G���G�C���H�
���_�H�H���t;H��tH�
�����H�>����H�
u���������H���2���f������1�H���������H�
H���������������밹D����������f�WVSH�� �H��tH�H��tH���tA�{$⭬t
��H�� [^_ËC��u+H�{H����������u݃C t3H�������"D1��ă�H�K�C�}���H�ى��s�����D��H�K��������ffffff.�WVSH�� H��H��tH�9H��tH���tE�$⭬t���H�� [^_�H�����������u�G��=����GtKH��H�� [^_�����H�
����H�H���t`H��tH�
���>�H�>�H�
���,��H�wH����������u�G )GH���G ��������t�H���}����S���1�H���.�����H�
������������.���닐WVSH�� H��H��tH�9H��tH���ts�$⭬t���H�� [^_�H�����������u�H�wH�������������D�GE�����W �G��~)��G �G��R�G��H�
�����H�H���thH��tH�
����H�>�]���H�
������T���H���v�������H��uR�h��������9�����/���H���L�����E�����1�H���������H�
_��������������������fD����������������SH�� ���������t��H�� [������H�� [�ff.�SH�� H���c������t
��H�� [�f�H��v��0���VSH��(H��H���/������t	��H��([^�H��t�H�0ɋ@���H��([^�DVSH��(H�ˉ���������t	��H��([^Ã�w�H�0ɉp ��ffffff.�VSH��(H��H���������t	��H��([^�H��t�H�0ɋ@ ���H��([^�DWVSH�� H��1�H��L��������u
H��u�H�� [^_�H��v���S@�H�� [^_��H��(��w
�H��(�����������f.�H��(�������v���������H��(�fff.�ATUWVSH�� D��H�ωщ�����9�}���H�� [^_]A\Ð���i���9��C�������w8L�g8L���,�������u�H�O�������t&�_@L�������f��C����C�븾��f�WVSH�� H��H��������t
�H�� [^_�H��t�>1������9�|�1������9�f��H���P1���f�ATUWVSH�� ��1�H��L�����������u���v
��H�� [^_]A\���u�}1�����9�}���1��[���9��G�������v�G����C�L�f8L����������u�H�N�������t
�~@L������냻��fDSH��0H�ɉ�u��u`1�H��0[��H�L$(�]�H�L$(H�H9�t�A��1ҹ���H��u����H���M�1҃��ƒ���T��f�����(������ffff.�SH�� H��H��u1�H�� [����H�H9�t�1�A�ع�V�H��u��[�H�����1҃��ƒ���T���H��(1����1�H��(Ð������������WVSH�� ���H��D��t���������H�� [^_�D���1jH��H��t)E1�1�A����?�����H��H�t1�H�H�� [^_Ð��f�H�ٻ��i뇐VSH��(H��H��tH�1H��tH�H������uH�3�U�������H��([^�H���i1�H��([^�f.�SH�� H��t&H�H��t1�H����=t,1�H�� [�@����������H�� [�����f�SH�� H��t&H�H��tH���������u1�H�� [��������������fff.�VSH��8H��H����H��A�����tB��R���C�� �i������H�L$ ����9��T$ �D$(E1�i���9�w!H�D��H��c�������u'1�H��8[^�@A��A)������A���DD��ʻ������������H��(H��tH�H��tE1��H������u���������H��(�@1�H��(�f�H��(H��tH�H��t��~E1�H��W���u�M�������H��(�D1�H��(�f�VSH��8H��H��tCH�H��t;H��t61�H����1�=t�L�D$ H�����T$ ��1��H��8[^����������H��8[^��H��(����(�����H��(�fDH��(����(�����H��(�fDH��(�n��(�����H��(Ð�����UWVSH��8�H��H�Ή��D$ tSH�L$ ������uS�|$ ~
���(t4����^fH��H��t�D$ ��~-�E�EH�.1ۉ�H��8[^_]��D$ �fDH�L$(�V�������tH�L$(����H����eH��H�D$(H�MH�T$(�8���������u�H�L$(�E�I�����SH�� H��H�
�����H�H���t"H��ۃ�H�
������H�� [�@H��1����������f�VSH��8H��H��t)H�H��t!H���tT�;t"1�A�H������t�H��8[^�H�K�T�����u�H�H���e1�H��8[^��H�
)����H�>��t�D$(H�

��O��D$(�H�0���fDVSH��8H��H��t7H�H��t/H���tM@A��H���T���t���t��t�H��8[^�1�H��8[^�H�KH��8[^����H�
���:�H�H���t&H��tH�
e����H��H�
S�����1�H���a���H�
:��D$(�x��D$(��u���fDSH�� H��tFH�H��t>H���tH�A�H���������tM��t8����D�H�� [�f��H�� [�D�H�� [�DH�KH�� [�r���f�1�H�� [��VSH��8H��H��tRH�1H��tJH���td�A�H���������t9��tt����D�H��8[^�H�
6��x��H��8[^�@�H��8[^�@H�
	����H�H���t)H��t�H�
���0�H�3�l���H�NH��8[^�a���1�H�������H�
���D$(����D$(���f�������������SH�� 1�H���1�����u
�{4t�C4H�� [�f.��H�� [�DWVSH�� H��1�H�����������t
��H�� [^_��g���H���t�H��H���$������uك~4�t�H�N���������u(H��tH�NH�������tH���z������듐��������WVSH�� H��H�׹� �aH�øH��t �������tH��t5H�C����H�{1�H�H�� [^_�H��1��2a�H�H�� [^_�f�1���fff.�UWVSH��(H��H��t>H�ytH�ytH�iH���V�����t2���H�~t	H�N�
���H����`1�H��([^_]��H�^H��t<�H��������u�H�{ H��H�CH�C ����H��H���]����H���s����y���ff.�WVSH�� H���x����������n�H�lj��������H��H�� [^_�VSH��8H;
�H��H�����b���H�¸H��t^H����H�{tZH��tUL��hM��L�L$ t'I9Yu�<�I9Yt*M�IM��u�H�D$ H�L$ I���������tH��8[^�L�L$ H����������H��8[^Ð����H��H���j���H��tH��t�H�{H���g����D1�H��8[^Ð�������%�����%����SH��0H��H�
���lH���H�D$ tv��7_H�
���KH�
��H�D$ �:L�D$(H�T$ H��H�D$(�_H�L$ H���&H�L$(H�B���H�9���^H��H��0[�H���J�H��H��H��0[�fDH��(�G���H���H��(Ð�����������H��(��t��t�H��(�f����H��(ÐVSH��(�=3mt
�'m��t��t?�H��([^ÐH���H�5��H9�t�H�H��t��H��H9�u�H��([^��Y��1�Ð������������H���fff.�H��Ð�����������VSH��8H�D$XL�D$`L�L$hH��H�T$XH�D$(�]H�r|H�H`�H�t$(�]H�H`H��I�����]�f.�AVAUATUWVSH��`H�΋
Y�H��L�Ņ���H�<�1�f�L�HL9�rH�P�RI�L9�����H��9�u�H���H��I����Hc�L�l$0L�4[H��I��L�H�C��A�T$A�0H�L��H�CH���H���J�L0��H��� �D$T�������A�0L��H����H���!�D$T��u5I��H��H��H��`[^_]A\A]A^�q\f�L�l$0H�D��f���@t�L�L$,A�@H�T$HH�L$0H����I��H��H���'\�D$T��@t��tL�L$,D�D$,H�T$HH�L$0�ӐH��`[^_]A\A]A^Ã�@�6���L�
êA�@H�T$HH�L$0M�����������|�H�
�z�������fD1��p���H�z�A�T$H�
�zN�D0����H�
UzH������H�
fzI��0�y�����UH��ATWVSH��`����tH�e�[^_A\]����O
H�H�@H��H����H�5�~H��~��H)�H�D$ H�ɩH��H)�H��~�H��~3D��~E����D��~E����D�
�~E��uH��~D�E��ut�K��um�S���H��H9��;���H�=����I������K��SH�H���L�������CH�
�yH�E��E���DH9������H�=`����KH�U�A�H��H���E��p���H9�rۋը1�1��������L�%��H�=���f���H��;5���t���H���H؋��t�H�HA�0H�U�A��H����H�d�L�M�H�U�H�M�D���먃� ����@����I)�LH�U�L�E�A�����H��H9�������@���D�	A��I��I����fE��IH�H)�L�A�H�U�H�U��x����D�	A��I��I�����E��IH�H)�L�A�H�U�H�U��D����D�	D��I��M	�E��IH�H)�L�A�H�U�H�U������T���Hr�H�
�wH�CL�C�P����H�
�w�����������H��(H��fH�H��t��H��fH�PH�@H��fH��u�H��(�ff.�VSH��(H�3Z�����t,��H�5#Zt����ƃ�u�H�
����H��([^����@1�H�5�Y�D�ÍC��H�<�u�봋����t��@���널���ATUWVSH��@H��fH�2��-�+H�D$ H9�tH��H��fH��@[^_]A\�f�H�L$ �=�L�d$ �����������:�H�L$0���m�L��H3T$0H�������H1�H1�H1�H!�H9�tH��H��H�fH�&fH��@[^_]A\�H��] �f���H�3��-�+��DUH��VSH��pH��H�
̥��H���E1�H�U�H����H��I����H�E�H�D$8I��H�U�1�H�D$0H�E�H�D$(H�x�H�D$ ���H�^�1�H�5ݥ�3�	��-�H�2�H�KeH�E�H�PeH�E����H�
�d�������	�H�������UH�EH��H�EH����x��������SH��0�=��wB=��rk�1ҹ�UH��H���H�Ҹt	���1�H��0[�@=����ws=����=��t��H��0[�fD=�����=���=�u�1ҹ�1UH����H���~���1��v���=��t[=��u�1ҹ��TH����H��tG���1��?���f�1�����f�=�t�=���=���1�H��0[�fD�H��0[�D��T1���������D$(�	�D$(��������[T1��������ET1�����fffff.�ATUWVSH�� ��H�ŋ����u%H��t H�
�s����IH��t�H�� [^_]A\�@H�5y��0L�%�1�H���H�L�� �H�H�=����H)��3�H�ͩA��	�<؋B�BI��H��H)�V�FH��H�� t3H����H��H��u�H���q�����I��H�
������W���� ��@VSH��(H�H�ˋ������� ��CCG ��=��vG=���,��=��t]=����@H�i�H��tGH��H��([^H���=��rI�1ҹ�RH����H��t���и����H��([^�fD�B�h�����@=�t���=�t�=��q���1ҹ�URH����H���R�������f�=��t�=���.����P���f�1ҹ�RH����H����������C���D1�����f�=�t�=�����������f����Q��������$@��������|Q��������hQ��������UWVSH��(H�
�����H���H��t3H�-��H�=������H���ׅ�uH��t	H�CH����H�[H��u�H�
�H�
>�H��([^_]H��UWVSH��(��1���H�ׅ�u��H��([^_]ú��MPH��H��t=�(H�xH�
��"�H��H�
ԧH���H�C�����H��([^_]þ����뚐SH�� ����˅�u1�H�� [��H�
�����H���H��t�9�u
�ND�A9�t'H��H�BH��u�H�
T���1�H�� [�fDH�HH�JH���pOH�
)������H�BH�>�H���ِH��(��tGr��t`�H��(�fD�ʦ��uf�����u�H�
Ԧ��������f������t'����H��(�f��z���t�������H�
���:��������듐��������1�f�9MZt��DHcQ<Hс9PEu�1�f�y���DHcA<H��AH�D�I��t(�I�H��L�L�(�HA��I9�wHH9�rH��(L9�u�1���fff.�WVSH�� H���NH��wkH�
Ԍ���_�����t[Hc���H�����H��PH�\�@��t9�@�H��H�|�(�	H��(H9�t"A�H��H���QN��u�H��H�� [^_�f�1�H��H�� [^_�SH�� H��H�
Q����������tH�
A���H��H)�H�� [������1�H�� [��H��(H�
�������1҅�tHc?���H������T��H��(�SH�� H��H�
����l�����tPHc
���H�ʋ��H��BH�D�R��t.�R�H��H�T�(f.��@' t	H��tH��H��(H9�u�1�H�� [�H��(H�
u�������1҅�H�e���HE�H��H��(�f�VSH��(1�H��H�
>����������u	��H��([^�H�
%���H��H)������H��t��X$������H��([^�@UWVSH��(��H�
����z�����tfHc���H�5؊��1틼���t:H��H������H��t*H��H�u
� ���H���J��u�B��t���jH�H��H��([^_]�D1�H��H��([^_]�f�SH�� H���H��tH�� [�f�1ɍY�F���H��tq���߀�MuF�P��߀�Su:�P��߀�Vu.�P��߀�Cu"�P��߀�Ru�P�у�߀�Tt��0��	v���H���c�H��H�)��t���H�
Yk���H���X������������������������QPH=H�L$rH��H�	H-H=w�H)�H�	XY�����������������������H�D$�H���� �H��HH�D$`L�D$`L�L$hE1�I��H��H�D$ �`H�D$8�0H��H����������H��8I��L�D$ H��E1��`�H��8��������������H��XI���*��������t�����B�D$D1��f���uO�B�D$D1�%�L��$�A�H�D$HL�L$0�L$ L�L$DH�
�XD�D$(H�D$8M����H��X���@t'�B�D$D�ÿ���@�D$D1�1��f��B�D$D�����>@�t����SH�� �BH����@u�R$9S(~�� u#HcC$H���S$���S$H�� [�f.�H��I�S$���S$H�� [�f�ATUWVSH��@L��H��L�D$,H�L$0��1��m4�C��x9�O�C9�})���C~�C	t{��~T�L�D$,H�L$0H���14��~:�@�H�|$0L�d1�H��H���!���L9�u������H�ڹ �����C�P����S�H��@[^_]A\��C�����f����Cf.�� H��������C�H����Ku��V����UWVSH��(A�@H�Ή�L�Å�x9�O�C9���)���C~)�C	u#���C� H���c����C�H����Ku�E���H�|t8f.��H��H���1���H9�u�C�P����S~H�ڹ �����C�P����S�H��([^_]��C�����H��8��A�@����tDH�L$ E�X�D$ -L�QA�� E1�B�
���D	�C�
I��I��u�I�RH)�������H��8�E�XA��tH�L$ �D$ +L�Q�A��@tH�L$ �D$  L�Q�f�H�L$ I���fDUH��WVSH��(D�BD�R1�H��I��E��AI�A��D�Htf�z ���FA9�AM�H�H��H����]���H)�A�€H�|$ tH���6A��D�VM��L���II��I����������FH9��[�F	t1f�~ t*H��H)�H��H��?H��>HЃ�H)�H���6fDI��H��I�XI��H��H��H�H)���0H��A�H��u�D�FE��~/H��H)�A�E��~!A�H�H��H�T@�0H��H9�u�H�\H9��v�F��~YH��H)�‹F�҉V~J��t���V�V������u-�V�J��҉N~ H�� ������F�P����V�F��to�-H��H9�s1H��H�������H9�u�F�P����V~H�� �r����F�P����V�H�e�[^_]�H�������@A�@,I�X�����f���t+�+H���f�D�ȺVUUU��D����)�A�����fD�@�`���� H���T������������V�J��҉N�$�����0�FH���P����V������I��I�������D�N�������0H���s���H���.����UH��AVAUATWVSH�� ���oL��E�@A�ʋw��D��H��I���ɺF�,�D�0���E��AI���D�$tf� ��D�_E9�D��AM�H�H��H����Z���H)�H��L�d$ �IE��L��A�� �I��S�M��t#D��H��D!ȍP0��9~��7I��D	�M�ɈC�u�I9��E���mL��H)�A�E���[A�H�H��H�T�0H��H9�u�H�\L9�����D)�A9��E��A)�E��D�o~(A��ot�G	tA�E�����A��D�GE���A�u�A��ot�G	tD��C0H��E��~;�G	u5A���A��H��� �����A�E���D�n�1���I�A)�A�u�L9�vH��H�������L9�u�E��~���H��� �����F���H�e�[^_A\A]A^]�f.�D��VUUU��D����)�A��?���fD�G���������A���������f�A��o������G	������0H�������G%=�����A��D��H�TH���0H��H9�u�Mc�����J�\+A���������f.�D�OE���N����0H���B����������L��w�����A�u�A���s���UH��ATWVSH��0�y�H�����Qf��t_HcFI��H��H�������H)�L�E��E�H�\$ H���,��~J�@�H�|f��H��H������H9�u�L��H�e�[^_A\]�H��.������H�e�[^_A\]�DH��.������Ő�E��@H�L�M�H�M�A��N.��~�U�f�V�F�8����V��@ATUWVSH�� D�lj�H�օ�L��E�A��D9��6A)�E�AE���&�CD9��A)�E��D�C�����A����D�C�f�E��~!����A��E��D�Ct�C���W���d�C���&�@���S��~�C%=����VUUUL�c �C��0��t��H��H����������C���aH����������Ct#�c��0��t��H��H���R����C�P����S�H�� [^_]A\�f.��C����A�������������C	�����f�{ ������O�VUUU������)ʃ������E�������D��)Ѓ��f�E����A��A9�u�D�C����DH�ڹ �����C�P����S�������H�ڹ-���������C	�����f�{ ������������)R9������I�غL�����������C���+�������f��C	�������@�������CDH�ڹ0�������x�����f�E���x���A��E�A�t���f.�H�ڹ+������������S�H�ڹ0�����C�P����S���VUUUL�c �����DH�ڹ0�c��������H�ڹ �Q����n����C	����f��	����C�5���ffffff.�WVSH�� A�L��E�H�A�gfffI��D��Ic�A��A����A��E)�t$A�gfffDD��A��A��A����D)�A��u�{,�SA9�AM��G9�S�C����L��I��A������K�C,H�ڃ��C�ȃ� 
���E�C�w���{H��H�������H�� [^_�)‰S�f�VSH��hD�B�)H��E�����|$PL�L$LH�T$0�H�D$PH�D$0H�D$XH�D$8H�D$HH�D$ �2���D�D$LH��A�����tc�L$HH��I���R����C�P����S~#DH�ڹ �����D�CE�H�E��D�K�H���+�H��h[^�f��BA��V����L$HI��H������H���+�H��h[^�ffffff.�VSH��xD�B�)H��A���7��|$`L�L$\H�T$@�H�D$`H�D$@H�D$hH�D$HH�D$XH�D$ �;���D�D$\H��A������A����|�CA9�t�C	��H��D�D$8�:D�D$8D)����C���L$XH��I�������C�P����S~[H�ڹ ����D�CE�H�E��D�K�H���*�H��x[^��C	uLH��D�D$8�%:D�D$8���C�L$XI��H���#���H���K*�H��x[^��BA�������k����BA�����D)��C�9����L$XI��H�������뜋S������ЉC����f.�AUATUWVSH��h�)H�����|$0����f%Ef=���|$8������#������f%Ef=��f����H�D$0f���?�S��w9H��xH�y��A�H��)���I��L��(H��)���H��H��H�l$@�>D�KH��E��E��A��A�� �1�S��~���SH����tb��	~kA��7E	�D�H��H����I��A��A9�D��u�H9�wE��u	D�kE��~�.H��H��v�W�H���H���W�w�1���u�H9�w	D�cE��x�A��0�D�J������@H�D$01�H���������������������׃�H�y������H9��kE��D�[A�E�����C��D��)���D��O�%����D�DD��gfff��A������D)�t#A�gfff����A��A��A����)ʉ�u�E��E9��HE)�A���[A�C�E�ۉC~H�ڹ �o����C�P����S�D�SA�€�A���#A��@�+H�ڹ0�0����KH�ڃ� ��X�����C��~&�C	t ���CH�ڹ0������C�P����S�H9�w'�M�C f��f�D$.tH�L$.I�غ�+���H9�t(H�����.t_��,t�H��������H�ڹ0�����C�P����S�KH�ڃ� ��P����Dc�K�H��H�������H��h[^_]A\A]�H�������놐A�€�C���������H�ڹ-�2��������D�[�����H�ڹ+���������H�ڹ ������������������I��H��U1�������x���H��UI��������d���D�K��E��~H�u�D$@.�0H�������S��A��H��t���f�VSH��hD�B�)H��E��xlA���|$PL�L$LH�T$0�H�D$PH�D$0H�D$XH�D$8H�D$HH�D$ �r���D�D$LH��A�����t1�L$HI��H������H���*%�H��h[^�f��BA�뉐�L$HI��H������H����$�H��h[^ÐAWAVAUATUWVSH��L��$A��H��D��L��A��`�4H�
sTD�8H�t$pD�t$x�D$|����DŽ$�����DŽ$�����fDŽ$�DŽ$�fDŽ$�DŽ$���$��-4H��t����0��v
�[&���؃���$�D�����D$<f��H�s������%��D�t$xDŽ$�����E1��D$|�����CE1�H��L�\$|H�-�S��tb�ȃ� H�_<Z����9��A������/��E���LA�M��tA����
���DA�A��GH�߄�u�H���H�s���N�����$�H�Ĩ[^_]A\A]A^A_�@H�T$pH���#���������HcD�H����A��L��A����H�0I��H����H���2��L�D$pH���(��������E��uD9t$x��I�$I�t$L�D$p�xI��H�T$`� �������A��I�$��A���&A��t
A������$�I����Q����D���H2H��H���]����H�5R�V����GA�A�<l�����H�_�GA������GA�A�H��������GA�A�<h�p���H�_�GA��`�����D$xI�t$�� ��D$x��I�$�(H�T$pH�L$@I���|$@�,����w�����D$xI�t$�� ��D$x��I�$�(H�T$pH�L$@I���|$@������7�����D$xI�t$�� ��D$x��I�$�(H�T$pH�L$@I���|$@�|���������A��L��DŽ$�����A�����L�D$pH�L$`�I���D$`����������L$x�A����A���ZIc$A��I�T$H�D$`��A��I����H�L$`H�T$p� ����[���A����A���I�D$E�$$A��L�d$`�[A��I������ut�H�T$`L�D$p�����	���f��D$xI�t$�� ��D$x�I�$�(H�T$pH�L$@I���|$@�����������L$xA��GH���T���f�A����GA�H���/���@E�������L$x�GH������E��������L$x�GH�������M��t�A�������NA�$I�T$��A��X�GI��E1�H�������E�������D�T$(L�\$0�L$x�D$\��.H�PL�L$\H�L$ZA��o��D�T$(L�\$0~
�T$Zf��$���$��G�<���@H�T$p���������E�������L$x�GH������E��������L$x@�GH�������fD�D$xI�t$�����A�$����fDDŽ$�����A�$I�t$L�D$pH�L$Z�I��f�D$Z�`���������D$xI�t$������A�$������E���&����L$x�GH���^����D$xI�t$�����A�$����fD�D$xI�t$��'���A�$�$���fD�GA�A�<6��<3������2�����H�_�GA������fDA���DD�����I�4$H��LI�|$I��H��HD�H���-L�D$p��H���]����������GE1�A�H���v����4�i���H�_�G�\���I�$I��H�D$`�3���I�$I��H�D$`�n�����$�I����~���DŽ$�L��$��GA�������0A��G�������$�I��f��:���Ic$I��H�D$`����A�$I��H�D$`������D$<DŽ$��D$x�N���H�T$p�%H������������H�D$`I��H�D$`�e����T$`I��H�T$`����E��uD�L$x�\$|����Hc�$�I��H�����H�D$`H�D$`�����D$`H�D$`�W���DŽ$�����I���GE1��������������������AWAVAUATUWVSH���)�$�E1�H��A��M��A�1L�ˉ����A�������wrH�zLHc�H����P�H�ƀ�9H�F��4L9�u�A��A�0�1E�a�A� L���H��$HH��$@�D� tH��$HH�2D	+(�$�L��H���[^_]A\A]A^A_Ë)1Ƀ� ~� f����9���BI�ƍE�M�N��H�L��M�D�L����H���
H��I9�s�L)�H��Hc�I�D�D��J�E���H���ɉ�u�A�F�D$`L����'����$�E����A�N����L���H��$@H��$HA��H�
K�aI�������f�H��$@H�
�JA�����H��$H�(I�������H��$@H��$HH�
�JA�������I������H��$�L��D�D$0�$�T$`�D$(D�D$0L�\$(A�D�L��E��H�� �*ȁ���A�����?A��H��H�� I	�D��L�T$(1��D$(D)Ɂ�5�\>J���Y
LJ�Y4J�X4J�X�~�*��Y
2J�X��,�fW�f.��L$h����E��DŽ$����H�� I	у|$hM��w6HcL$hH�mJL�L$(�L$(��f.����l$hDŽ$��T$`DŽ$�)ƒ��T$p�E�T$h���y�T$hT$pDŽ$���$���$0	����$0����$01���$0��	����$0��	�*Ÿ����1�DŽ$�DŽ$�������$�DŽ$8�Y�H�,ȃ���$��T$HD�D$0L�L$8L�\$@�I�NjG�T$HD�D$0L�L$8L�\$@�����D$lt �MD$l���D$lt
�+D$l�D$l�����T$lT$h����$�L�L$(DŽ$��d$(��t�YHf.���f(ċ�$��X��XPH�D$(L�T$(L��A���H�� ����H�� I	…��(��$�f(�E1ɋ�$����G�H�H�^HL�T$(�HDŽ$�Hc��T$(�^��,�I�w�\��*҃�0A��\�f.����-�Gf(��\�f.��������$���9‰�$����iG�2�f(��\�f.��������$���9Љ�$���Y��Y��,��*҃�0�H���\�f.�v�f.�E�az��	A��i������L���6"��$�)D$`E��5���f�Hc�A�V��A�D���)‰T$`�����f�DŽ$0�=����*�����$0����$0�-���DŽ$���$8L$h��$����ɉ�$��	����$���!��3����DŽ$��M���f(��X��X F�D$(L�T$(L��A���H�� ����H�� I	�f(�L�T$(�L$(�\�Ef.��	��EfW�f.���d$(L�\$(E�����D$h;G����$�Hc�H��E�Ѕ��L��$8�����:��$������YfEL�\$(�D$(f.���D�d$h1�H�D$xA��I�wA�11�A� H���
H�|$x�s���H;|$x�)H�L$x���Y����D��$�E����+l$`�WD���E)�9щ�$��a��$0�S��$0�EA)�A�@D��$���$�E��~��$0~
9�$��!��$���$���$�D$p�PH�D$x�T$p��~#��~9t$p�D$pO�)�$�)D$p��$�)Ƌ�$���~S��$������~1H�L$x���FL��H��H�D$x�L��H�D$H��H�D$HI�Ƌ�$�)�����H�ŋ�$���~��$�H����H�Ń�$0DŽ$����$����t�E��H��|���+|$p��$��������$�����~L����I�Ƌ�$��T$p…�~H���H�ŋ�$�����D��$�E������$0����$���u;E1�H���L��H��H���Q��~D�d$hA���z���1�H�D$xD��$8L��1�A�A���d���f����D$p��$�����f.��*�f.�z�����l$h����fD�L$h)�$�DŽ$��ى�$��}�����$���$�H�D$x����D��$�E����>��~H�L$x�nH�D$xD��$�L�L$xE���.H��$�DŽ$�L��H�|$xH�l$XL��L�|$pL�l$`��L���x��$0	�uH�D$`�uD�D$lE���	E���uD�$0uH�T$`��]����D�&��$�H��9�$��LE1�L��
�aE1�H9�I�ƺ
H�����EH��E1��
H���2H�Ã�$�H�T$XL���5H��L��A��D�`0�CH�L$XH��A���D�HI��E������H��L��H�D$0�L�D$0���������H��H�����$0�������$���$���)�9�$�}��+�$�1��$���$���$����Y��$���$���$�������$�L���5I������H�������H���������DŽ$��7���DŽ$�D��$8E������$8A�Nj�$8��$8��$�D����$�!‰�$��M���DŽ$��H��L�������2���E1�L��
�l$h�vI�Ƌ�$�������$���$0����$���$�DŽ$�L����$��"�L��E1��
���$�I��H��L���
D�`0D�&H��;�$��1��T$l���s�|$l��A�~���V���P�H�ƀ�9H�F��$L9�u�D�d$hA�1A� A������L�\$(DŽ$�I�w�D$(f(��^��,��*ȍP0A��Y��\�f.����$�9�$�����=��$�f(����$�9���f(ȃ���$��Y�f(��^��,��*��P0�H���Y��\�f.�f(�z�f.�u�D�d$hA��E1�������|$`������G��A9��������$��D$pDŽ$�������$�DŽ$����!�����A�DŽ$8�v���D�T$lE�����|$l�;D�d$hA�������A�1�H�D$x����L�T$(�H�H�=�\$(L�\$(Hc�DŽ$�L���Y��D$(�s<���Yƒ���$�f(��,х�t�*��\�f(���0���$�H��9�u��
^<f(��X�f.��c����\�f.��X���f.��4�.E1��f��P�H�ƀ�0H�F�t�E�a�I����L$lI�ى�E��H�l$XL�|$pH��$�����A�~���|$l��M��H�\$P�G�D�&E1�L��
H����L9�L��
HD�E1�H���H��H��I����	D�`0I��L��H�������A��9M��H�\$P��A��A� D�&D�d$hH��L�L$xA�������L���H��H��I���������u
A���s���A�~�VA��f�H�ƀ~�0H�F�t�D�d$hA��������$�DŽ$�1�+�$��0���A�I�H�T$xH�HH��HcBH��L���c�H����I�������|$l����A��9I��H�l$XL�|$pH��$���E�l$D�d$hL�L$xD�.H��A� A��������X�f.��Of.��V�D�L$hz
u�����A������I��H�l$XL�|$pH��$�L�L$x�"���D��$�E���u���D��$�E��������
|9A������Y�f(��L$(L�\$(�Yc9�Xc9�D$(L�T$(L��A���H�� ����H�� I	‹�$�����D�d$h��A� �A�������A�~�Z�������L��D�D$0L�L$8�H��H��I���s��D�D$0L�L$8��A��9tJE�`1A� A�~��A��{����V�D�L$h�����A�F������E1�������������9L�L$xH���9����E1��A��9I��E��H�l$XL�|$pH��$�t�E����E�`1A� ����H�L$xE1��
�m��$�H�D$x
��$0H��$���$�����������h���A�~�DE�����u
A�������A� �������$���$�����A�~A��i���A�~E�A��A���U���E1�A�~�����������$���$��t�����������������H��XE��D��f�T$huf���wR��H��X�H�T$LD�L$(H�L$ �D$LH�D$0A�H�T$8L�D$h1҉�����t�T$L��t��y�*�����H��XÐWVSH��0H�ڗH�\$ H�ɉ֋8HE���#��A��H��A���K���H�H��0[^_ÐAVAUATUWVSH��01�I��H��L���q#I�>A��H�|�H��D�(tBH��tiH��uf��NHc�H�H΀{�tDH��H9�v6�E��E��H����������H������H��H��0[^_]A\A]A^��I�>��I�H����H��u$���HcЃ�H�Hր| t"H��H9�v��H�L$ E��E���b�������H��댐�����VSH��XH��H��H���.M���2�A�A��D$@������$�v�|$@��L�D$8L�L$0��$��=���L�D$8L�L$0tOI�����D$(H�t$ A�I�غ��$��������H��X[^�f���$���uE�f��H��X[^�f�1�H��X[^�f��T$A�D$(A�H�L$ L�D$@�f��D$(H�t$ A�I�غ��$������t��1�H��X[^�@���������*������{����A�������k���@UWVSH��XH�)�H�\$NH��L��H��f�D$N�(HE�L�D$8�� L�D$8L�
iH���l$(�D$ H��LE�H���%���H�H��X[^_]�f.�AVAUATUWVSH��@H�-?iM��I��H��IE�L���� A��H���M��D� tsI�H��tkH��tj1�H��u�II�Hc�H��H�H�H9�I�v!I��H��D�d$(I)�D�l$ I����������Dž�uH9�sI�H��H��@[^_]A\A]A^�f�1���H��f�D$>t�D��1��f�I�H�H�H�H9�I�v�H�L$>D�d$(D�l$ I��I����������ffff.�UWVSH��HH���H��H��L��f�D$>�(�yH�hH��H�L$>�l$(�D$ I��HD�H��I������H�H��H[^_]Ð����SH�� 1ۃ�~�����P9�|���,�H��H�� [�VSH��(H��D��H������D�H�KE��D�I��tf�D�	I��H��E��E�u�H��tL�H��([^�ffff.��H�ȋI���HH�H��P�@AWAVAUATUWVSH��81��rI��H��A;u�J��H�ZM�eLc�I��F�D�C�D�J�l�1�A��A����A�ƉD$,����I��M��1�E1�DE�I��L��J�<E�H�����H�� I)�M)�M��E�I��I�� A��L9�s�G�\�E��u5K�D�H�PH��I9�sD�R�E��t
�D�E��uH����I9�r�A�uH��L���-��xtA��L��1�D�t$,D��H��L)�H)�H�‰H��H�� ��H9�s�Hc�H��E�D�E��u1I�D�H�PH��I9�s�J���t����uH����I9�r�A�u�D$,H��8[^_]A\A]A^A_�VSH��(����e�΅�u�؉5�eH��([^�f�����H�0H�����H��t&���Љle����H��([^�f��v�@H��(�j��u�,eH��(���;���H��/H���#�H��t�к��d�'H��(Ë�d1��됐��VSH��(�DnHc��t@��uf���/n��uNH�
DnH�����H�
\n��H�
�������mH��H�nH��H�F�H��([^H����t6��m��uH�>�fD��Ӌ�m��t��t�H��([^���m�fD�=�mt��DHc�H��mH��H��H�O�H��@SH�� ���Om��t
H�� [�@H���H�
Rm��H�
qmH��H�� [H��fffff.�WVSH�� ��1�������	H��cHc�H��H��t\H�H���3����G�H�H��'H���	H���
H��H��t�s�{1������C�CH��H�� [^_É�H�N��G�H��H�H��'H�ecH)�H��H�Ѓ��H��H�H= w�H��H��fff.�SH�� H��H��tC�y	-1������HcSH��bH��H��H�1�H�� [�d���@H�� [�F
fDH�� [�f.�UWVSH��(�qE1�L�YH��Ic�Hc�DG��L��I�L��G��I��H�� D9��H��t;w}Hcƃ��\��wH��H��([^_]ËO���S���H��H��t3H�HHcGH�WL���
H��H������Hcƃ��\��w�1��@SH�� �˹�����H��t
�X�@H�� [�f.�AWAVAUATUWVSH��(LcaLcrH��I��E9�}D��H��Mc�I��Lc�1�C�44;s��K����H����Hc�H�xH�l�I��H9�sA�I��L9�w�L�kM�WJ�\�O�d�M9�sNfDE�I��E��t3H��L��E1�D�D�2H��M��M�M�M��D�H��I�� H9�w�D�
H��M9�w���~#D�E�H�U�E��t�DH���
��u��u�pH��([^_]A\A]A^A_�ffff.�UWVSH��(��H�ωӃ�������tQH�5jH��u����t<L�M��tDL����t�H��H������H��H��tmH��H���>�����u�f.�H��H��([^_]�@������H�.H��t@�H������랃�H��+E1�H����H���H��H���T���1�H��H��([^_]�H��H������H��H��H�t�H�롹����H�5>iH��t��/����)����q����H��H��H�it�H����AUATUWVSH��(H�ω�A��D�g���G�IA�A�\$9�~���9���B���H��H������L�H~E1�C��I��D9��F�L�L�HcGD��L�G��H�t�t]� E1�)�E���A���E	�E�E�I��I��A��L9�w�A��E��E�AE܃�H���]����H��H��([^_]A\A]ÐA�I��A�I��L9�w���ff.�LcJ�AD)�u+N��L�AJ�T
J�L	H��H��D�
D9	uI9�r��������f.�WVSH�� H��H�����������1��K����H���D�[�pL�CL�HL�WIc�H�t�HcWH�|�1�fDA�A�I��I��H)�H)�H��A�	I��H�� �˃�L9�w�L9�M��L��v;f�A�I��H)�H��A�	I��H�� �˃�L9�w�H��H�7H��M�L�I����ufDI��A��E�E��t�D�XH�� [^_�@1��)���H��t)�@�@H�� [^_�H�ؾH��H�������1���VSH��HcAA� H�qL�T�I�ZM�ZD�K�A����A)���
D�I�D��E1�)�����?H�� L9�sD�C�A��HD����D	�H	�H�D$�D$H��[^�@1�L9�s�S�M��A��A��t?A�+D��1�A)�A���D��A���?��A	�I�� I9�vA�[����D����	�L	��D��
�?H�� H	��f.�WVSH��0��D$(H��L��H�\$(�����H����I��I�� E��A�����A����A��D�ʁ�E��DEʅ�teD��D����E����� D��D)����	ىHD��A��A��D�HɃ�E�҉HuDHc���A��2�T�D���)щH��0[^_�A���@A��E��D�Y D�H�t�C��������5D)ډH��0[^_�@�X�ff.�H���H���
H���Ɉu��Ð�������UWVSH��H�yHcI����9���H�L�\�H����L��I�htD�L�� ��I��)�A��M9���I��A�������D	�A�E�I��I��A��M9�w�I)�I�C�H��H�D�E��D�tSH��H)�H���M@�C�C[^_]�I9�H��H��v�f��H���
H��I9�w�H��J�DH��H�D�H)�H�����Ct�[^_]�H���fDHcAH�QL�D�L9�s(�I1���t��
��uH���� I9�w�������1�@Ð��������������H�	c��fDH��(1ҹ��.H���H��tH�HH��(��1�H��(�f�VSH��(����H��H��t-H��$H��H�5Ă��H��H��t.H��([^H��DH�y���H��H��([^H��f�H�m$H����H��H�JbtȋH�/���H��H��([^Ð�%B����%�����%����%�����%����%�����%�����%�����%�����%�����%ƒ���%�����%z����%*����%�����%"����%z����%ƒ���%ʃ���%ڃ���%ڃ���%r����%�����%r����%�����%�����%�����%�����%"�����%2����%�����%ʁ���%b����%�����%����%�����%ҁ���%ڀ���%Z����%2����%�����%����%€���%ʀ���%�����%����%
����%z����%����%€���%z����%�����%:����%�����%Z����%b����%����%r����%����%����%R����%J����%J����%J����%�����%Z����%J����%B����%R����%�����%�����%�����%�����%ʀ���%����%Ҁ���%r����%����%*����%����%����%�������������������� Рg(Рg��������0c�g�àg��g��g@ÿ���?��g���g2��-�+�] �f���KERNEL32.DLLInterlockedCompareExchangeQUSEREX.DLLQueueUserAPCExQueueUserAPCEx_InitQueueUserAPCEx_FiniMingw-w64 runtime failure:
Address %p has no image-section  VirtualQuery failed for %d bytes at address %p  VirtualProtect failed with code 0x%x  Unknown pseudo relocation protocol version %d.
  Unknown pseudo relocation bit size %d.
.pdatamsvcrt.dllNaNInf(null)(null)PRINTF_EXPONENT_DIGITS����k���k�������k���|���k������k���k���̰������k�������l���k���<���k���k���k���k���k���k���k���k���k���k���k���k���k���k���k���k���!���k������k���̱��|���\���k�������k���k���L���k���k���k���k���k���k������k���k���k���k�������k���k���k���k���k���k���k���k������k������\���ܮ������\���,���\������k������������������L���k���k�������������k���k�������k������InfinityNaN0Ǵ��������0�������?aCoc���?��`�(��?�y�PD�?�}�-�<2ZGUD�?�?$@@@@��?_set_output_format_get_output_format�?$@Y@@�@��@j�@��.A�cA�חAe��A _�B�vH7B��mB@�0�B�ļ�B4&�kC��7y�AC�؅W4vC�Ngm��C=�`�X�C@��x�DP����KD��M���D��ؗ�Ҝ<3���#�I9=��D��2�����[%Co�d(�
��7y�ACn����F��?�O8M20�Hw�Z<�s�Ou}___lc_codepage_func__lc_codepageKP�� o(p�0�8X@`�L��X��\��`5l@KxPr|�>�@����������/�0a�pz�����<�@���a�p�����8@s�]$`�4��<��D�H � L� � \� �"d�"S$t`$�%�&�&�'�'�(x)��)�)��)*� *�*��*�*�+	+�+#+�0+7+�@+�,��,. .t.�.R/`/P0(P0@14@1�1@2�2L�2�2T�2�2\33d 3Q3h`3�3l�3�3p�3B5tP5E8�P8
9�9v:��:m;�p;u;��;�;��;�;��;�<��<�<��<K>�P>�>��>�>�?R?�`?q?��?�?�@&@�0@�A�AqB�B/C0CiC$pCD,D�D8�DnEHpE�EP�E�EX�ELF`PFSFl`FcFppF�Ft�F
G|G�G��GH� HeI�pI�I��I�I��I�I�J1J�@J?K�@KhL�pL�M��M^O�`O�OP�PQERPR�R(�R�R0�R�R8S1SD@S{SP�S�S\�S�ShT$Tp0T�Tx�TU� U�U��USV�`V�V��V�V��VoW�pW�W��W'X�0XtX��X)Y�0YwY��Y�Y��Y9Z@ZZZ`ZzZ�Z�Z�Z�[$�[�[4�[�\<�\Z]H`]�]T�]�^\�^_h _�_p�_$`|0`�`��`0a�0ab�0b�b��b�b�c/c�0c�c��c�c��c�c��c�c��c&d�0dXf�`fJiPi�i�i�i�ij(j�j,�j�k<�k�mL�m|nT�n]pd`p�pp�pOq�Pq�q��q�r��r�r��rs�s�s��s�s��st�t�t��t�t��t�t�u�u��uIv�PvSv��v�v��v�vw!w0w�wxWx`xOy Py
z0z�z@�z}H�}}�X��l�pp�ф�������������6��@�g��p��� ������b��p���/�0��  ���4���@��P �{�d����t���|�,��0������,��0������J��P�|����µ�е�������������������H�	P�E�$	P���8	��ټ<	�ƽH	нվT	���`	���d	�A�p	P�Z�t	`���x	��/��	20

20`pP�B0`pP�2020B0`B0`B0`B0`R0`pB0`pPR0`p20BB0`pPB0`pPB0`�0B0`pPB0`20

20`pP�2020

20`pP�20

20`pP��0`p0`pP20`pB0`pPR
0	`pP���B20B0`B0`B0`pP

r0`pP�20B0pb0`b0`20`p2020Bb0`r0`pb0`b0`b0`20`pb20`pBB�2020B0`pP��2020`p30`pPr0B20b0`r020B0`pP20B0`pP20B20`pB0`pP

r0`pP��0`pP��20`p20`p20`p2020B0`B0`B0`20`pBB

20`pP�20`p

20`pP�R020B20`pB0`2020b0`BBb0`BBBb0`pP20b0`b0`20b0`2020`p20`pB0`pP20`pb0`R0BBB0`b0`�
0	`pP���
�

�	0`p�PBB0`

r0`pP�
�

�0`PR0

20`pP�B0`B0`pPB0`pP20B20`p20B20BB0`B0`pP20�b�20

r0`pP�B0`pPbEB0`pP	U2
0`p
���P
U

R	0`p�P

20`pP�20`p�0`�0`�0`pP���0`
0`
p	P����h0`
p	P�����R0`pR
0	`pP����0`�0`pPr
0	`pP����0`pP20B0`	b0`
p	P����B0`BB0`2020`p20B0`pP20	B0`
p	P����B0`pPB0`pP��20`p"0`R0`p0`pPBB0`��nR�4ss(0�1�3P0`/�@S�R�R@��p`S�TPRP�@����0�'�  &`$�"��`�(�;�^+�)0+�S�`�; _�_0` *�:@1�3P59P8�2�;3�3�2p; 3`3�<�* HG@J@K�MPQ`OpL�I�IpIJ�,�@+ U0a�[�Z�\�]`]��?�<P>`?�>?PF�@�ST`V�U�V`ZpW�Y�V@Z0Y�Y�X�W�Z0X�4�4�4�4565Q5m5�5�5�5�5�56696O6i6�6�6�6�6�67787G7^7s7�7�7�7�7�7�7
8)888I8X8f8s8�8�8�8�8�8�899(9;9N9f9|9�9�9�9�9�9:3:P:j:�:�:�:�:�:�:;!;:;P;f;�;�;�;�;�;�;<&<<<P<e<w<�<�<�<�<�<=#=B=a=�=�=�=�=�=�=>>'>1>=>J>S>\>e>w>�>�>�>	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrpthreadGC_64.dllpthreadCancelableTimedWaitpthreadCancelableWaitpthread_attr_destroypthread_attr_getdetachstatepthread_attr_getinheritschedpthread_attr_getschedparampthread_attr_getschedpolicypthread_attr_getscopepthread_attr_getstackaddrpthread_attr_getstacksizepthread_attr_initpthread_attr_setdetachstatepthread_attr_setinheritschedpthread_attr_setschedparampthread_attr_setschedpolicypthread_attr_setscopepthread_attr_setstackaddrpthread_attr_setstacksizepthread_barrier_destroypthread_barrier_initpthread_barrier_waitpthread_barrierattr_destroypthread_barrierattr_getpsharedpthread_barrierattr_initpthread_barrierattr_setpsharedpthread_cancelpthread_cond_broadcastpthread_cond_destroypthread_cond_initpthread_cond_signalpthread_cond_timedwaitpthread_cond_waitpthread_condattr_destroypthread_condattr_getpsharedpthread_condattr_initpthread_condattr_setpsharedpthread_createpthread_delay_nppthread_detachpthread_equalpthread_exitpthread_getconcurrencypthread_getschedparampthread_getspecificpthread_getw32threadhandle_nppthread_joinpthread_key_createpthread_key_deletepthread_killpthread_mutex_destroypthread_mutex_initpthread_mutex_lockpthread_mutex_timedlockpthread_mutex_trylockpthread_mutex_unlockpthread_mutexattr_destroypthread_mutexattr_getkind_nppthread_mutexattr_getpsharedpthread_mutexattr_gettypepthread_mutexattr_initpthread_mutexattr_setkind_nppthread_mutexattr_setpsharedpthread_mutexattr_settypepthread_num_processors_nppthread_oncepthread_rwlock_destroypthread_rwlock_initpthread_rwlock_rdlockpthread_rwlock_timedrdlockpthread_rwlock_timedwrlockpthread_rwlock_tryrdlockpthread_rwlock_trywrlockpthread_rwlock_unlockpthread_rwlock_wrlockpthread_rwlockattr_destroypthread_rwlockattr_getpsharedpthread_rwlockattr_initpthread_rwlockattr_setpsharedpthread_selfpthread_setcancelstatepthread_setcanceltypepthread_setconcurrencypthread_setschedparampthread_setspecificpthread_spin_destroypthread_spin_initpthread_spin_lockpthread_spin_trylockpthread_spin_unlockpthread_testcancelpthread_timechange_handler_nppthread_win32_process_attach_nppthread_win32_process_detach_nppthread_win32_test_features_nppthread_win32_thread_attach_nppthread_win32_thread_detach_npptw32_get_exception_services_codeptw32_pop_cleanupptw32_push_cleanupsched_get_priority_maxsched_get_priority_minsched_getschedulersched_setschedulersched_yieldsem_closesem_destroysem_getvaluesem_initsem_opensem_postsem_post_multiplesem_timedwaitsem_trywaitsem_unlinksem_waitP@,LCB�L�DC�L�E�E�E�EF*F<FTFbFvF�F�F�F�F�F�FGG4GHG\GlG�G�G�G�G�G�G�GH&H4HDHZHnH�H�H�H�H�H�H�HII*I6I@INI\IxI�I�I�I�I�I�I�IJJ,J<JFJPJ\JdJnJxJ�J�J�J�J�J�J�J�J�J�J�J�J�JK
KK K*K4KFK�E�E�EF*F<FTFbFvF�F�F�F�F�F�FGG4GHG\GlG�G�G�G�G�G�G�GH&H4HDHZHnH�H�H�H�H�H�H�HII*I6I@INI\IxI�I�I�I�I�I�I�IJJ,J<JFJPJ\JdJnJxJ�J�J�J�J�J�J�J�J�J�J�J�J�JK
KK K*K4KFKUCloseHandle�CreateEventA�CreateSemaphoreA�DeleteCriticalSection�DuplicateHandle�EnterCriticalSectionmFreeLibrary�GetCurrentProcess�GetCurrentProcessId�GetCurrentThread�GetCurrentThreadId�GetExitCodeThreadGetLastError#GetModuleHandleAUGetProcAddressVGetProcessAffinityMask�GetSystemTimeAsFileTime�GetThreadContext�GetThreadPriority�GetTickCount�InitializeCriticalSectionIsDBCSLeadByteExILeaveCriticalSectionLLoadLibraryAOLoadLibraryWwMultiByteToWideChar�OpenProcess�QueryPerformanceCounter�ReleaseSemaphore�ResetEvent�ResumeThread�RtlAddFunctionTable�RtlCaptureContextRtlLookupFunctionEntry
RtlVirtualUnwindPSetEventiSetLastError�SetThreadContext�SetThreadPriority�SetUnhandledExceptionFilter�Sleep�SuspendThread�TerminateProcess�TlsAlloc�TlsFree�TlsGetValue�TlsSetValue�UnhandledExceptionFilter�VirtualProtect�VirtualQuery�WaitForMultipleObjects�WaitForSingleObjectWideCharToMultiByteN__dllonexitS__iob_func[__mb_cur_maxx_amsg_exit�_beginthreadex�_endthreadex�_errno�_ftime_initterm�_lock(_onexitV_setjmp�_unlock�abort�atoi�calloc�exit�fputc�free�getenv�localeconv�longjmp�mallocmemcpysetlocalesignal)strchr/strerror2strlen5strncmplwcslenWSAGetLastErrorWSASetLastError@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@KERNEL32.dll@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@msvcrt.dll(@(@WSOCK32.dll�g0c�gc�gA`�gD`�g|�g0P�g���@�P�`�h�����P�0�8�`����

deps/libogg/README

********************************************************************
*                                                                  *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
*                                                                  *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2011             *
* by the Xiph.Org Foundation http://www.xiph.org/                  *
*                                                                  *
********************************************************************

= WHAT'S HERE =

This source distribution includes libogg and nothing else. Other modules 
(eg, the modules libvorbis, vorbis-tools for the Vorbis music codec,
libtheora for the Theora video codec) contain the codec libraries for
use with Ogg bitstreams.

Directory:

./src  		The source for libogg, a BSD-license inplementation of 
		the public domain Ogg bitstream format

./include       Library API headers

./doc           Ogg specification and libogg API documents

./win32		Win32 projects and build automation

./macosx	Mac OS X project and build files

= WHAT IS OGG? =

Ogg project codecs use the Ogg bitstream format to arrange the raw,
compressed bitstream into a more robust, useful form.  For example,
the Ogg bitstream makes seeking, time stamping and error recovery
possible, as well as mixing several sepearate, concurrent media
streams into a single physical bitstream.

= CONTACT =

The Ogg homepage is located at 'https://www.xiph.org/ogg/'.
Up to date technical documents, contact information, source code and
pre-built utilities may be found there.

BUILDING FROM TARBALL DISTRIBUTIONS:

./configure
make

and optionally (as root):
make install

This will install the Ogg libraries (static and shared) into
/usr/local/lib, includes into /usr/local/include and API
documentation into /usr/local/share/doc.

BUILDING FROM REPOSITORY SOURCE:

A standard svn build should consist of nothing more than:

./autogen.sh
make 

and as root if desired :

make install

BUILDING ON WIN32:

Use the project file in the win32 directory. It should compile out of the box.

CROSS COMPILING FROM LINUX TO WIN32:

It is also possible to cross compile from Linux to windows using the MinGW
cross tools and even to run the test suite under Wine, the Linux/*nix
windows emulator.

On Debian and Ubuntu systems, these cross compiler tools can be installed
by doing:

    sudo apt-get mingw32 mingw32-binutils mingw32-runtime wine

Once these tools are installed its possible to compile and test by
executing the following commands, or something similar depending on
your system:

    ./configure --host=i586-mingw32msvc --target=i586-mingw32msvc \
         --build=i586-linux
    make
    make check

(Build instructions for Ogg codecs such as vorbis are similar and may
be found in those source modules' README files)

$Id: README 18048 2011-08-04 17:36:32Z giles $

deps/libogg/doc/libogg/oggpack_read.html

<html>

<head>
<title>libogg - function - oggpack_read</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>libogg documentation</p></td>
<td align=right><p class=tiny>libogg release 1.3.0 - 20110804</p></td>
</tr>
</table>

<h1>oggpack_read</h1>

<p><i>declared in "ogg/ogg.h";</i></p>

<p>This function reads the requested number of bits from the buffer and advances the location pointer.
<p>Before reading, the buffer should be initialized using <a href="oggpack_readinit.html">oggpack_readinit</a>.

<br><br>
<table border=0 color=black cellspacing=0 cellpadding=7>
<tr bgcolor=#cccccc>
	<td>
<pre><b>
long oggpack_read(oggpack_buffer *b,int bits);
</b></pre>
	</td>
</tr>
</table>

<h3>Parameters</h3>
<dl>
<dt><i>b</i></dt>
<dd>Pointer to an <a href="oggpack_buffer.html">oggpack_buffer</a> struct containing buffered data to be read.</dd>
<dt><i>bits</i></dt>
<dd>Number of bits to read.</dd>
</dl>


<h3>Return Values</h3>
<blockquote>
<li>
<i>n</i> represents the requested bits.</li>
</blockquote>
<p>

<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2000-2011 Xiph.Org</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/">Ogg Container Format</a></p></td>
</tr><tr>
<td><p class=tiny>libogg documentation</p></td>
<td align=right><p class=tiny>libogg release 1.3.0 - 20110804</p></td>
</tr>
</table>


</body>

</html>

deps/libogg/doc/libogg/oggpack_read1.html

<html>

<head>
<title>libogg - function - oggpack_read1</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>libogg documentation</p></td>
<td align=right><p class=tiny>libogg release 1.3.0 - 20110804</p></td>
</tr>
</table>

<h1>oggpack_read1</h1>

<p><i>declared in "ogg/ogg.h";</i></p>

<p>This function reads one bit from the <a href="oggpack_buffer.html">oggpack_buffer</a> data buffer and advances the location pointer.
<p>Before reading, the buffer should be initialized using <a href="oggpack_readinit.html">oggpack_readinit</a>.

<br><br>
<table border=0 color=black cellspacing=0 cellpadding=7>
<tr bgcolor=#cccccc>
	<td>
<pre><b>
long  oggpack_read1(oggpack_buffer *b);
</b></pre>
	</td>
</tr>
</table>

<h3>Parameters</h3>
<dl>
<dt><i>b</i></dt>
<dd>Pointer to an <a href="oggpack_buffer.html">oggpack_buffer</a> struct containing buffered data to be read.</dd>
</dl>


<h3>Return Values</h3>
<blockquote>
<li>
<i>n</i> is the bit read by this function.</li>
</blockquote>
<p>

<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2000-2011 Xiph.Org</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/">Ogg Container Format</a></p></td>
</tr><tr>
<td><p class=tiny>libogg documentation</p></td>
<td align=right><p class=tiny>libogg release 1.3.0 - 20110804</p></td>
</tr>
</table>


</body>

</html>

deps/libogg/doc/libogg/oggpack_readinit.html

<html>

<head>
<title>libogg - function - oggpack_readinit</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>libogg documentation</p></td>
<td align=right><p class=tiny>libogg release 1.3.0 - 20110804</p></td>
</tr>
</table>

<h1>oggpack_readinit</h1>

<p><i>declared in "ogg/ogg.h";</i></p>

<p>This function takes an ordinary buffer and prepares an <a href="oggpack_buffer.html">oggpack_buffer</a> for reading using the Ogg <a href="bitpacking.html">bitpacking</a> functions.

<br><br>
<table border=0 color=black cellspacing=0 cellpadding=7>
<tr bgcolor=#cccccc>
	<td>
<pre><b>
void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
</b></pre>
	</td>
</tr>
</table>

<h3>Parameters</h3>
<dl>
<dt><i>b</i></dt>
<dd>Pointer to <a href=oggpack_buffer.html">oggpack_buffer</a> to be initialized with some extra markers to ease bit navigation and manipulation.</dd>
<dt><i>buf</i></dt>
<dd>Original data buffer, to be inserted into the <a href="oggpack_buffer.html">oggpack_buffer</a> so that it can be read using bitpacking functions.
</dl>


<h3>Return Values</h3>
<blockquote>
<li>
No values are returned.</li>
</blockquote>
<p>

<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2000-2011 Xiph.Org</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/">Ogg Container Format</a></p></td>
</tr><tr>
<td><p class=tiny>libogg documentation</p></td>
<td align=right><p class=tiny>libogg release 1.3.0 - 20110804</p></td>
</tr>
</table>


</body>

</html>

deps/libvorbis/README

********************************************************************
*                                                                  *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
*                                                                  *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
* by the Xiph.org Foundation, http://www.xiph.org/                 *
*                                                                  *
********************************************************************

Vorbis is a general purpose audio and music encoding format
contemporary to MPEG-4's AAC and TwinVQ, the next generation beyond
MPEG audio layer 3. Unlike the MPEG sponsored formats (and other
proprietary formats such as RealAudio G2 and Windows' flavor of the
month), the Vorbis CODEC specification belongs to the public domain.
All the technical details are published and documented, and any
software entity may make full use of the format without license 
fee, royalty or patent concerns.

This package contains:

* libvorbis, a BSD-style license software implementation of
  the Vorbis specification by the Xiph.Org Foundation 
  (http://www.xiph.org/) 

* libvorbisfile, a BSD-style license convenience library
  built on Vorbis designed to simplify common uses

* libvorbisenc, a BSD-style license library that provides a simple,
  programmatic encoding setup interface 

* example code making use of libogg, libvorbis, libvorbisfile and
  libvorbisenc

WHAT'S HERE:

This source distribution includes libvorbis and an example
encoder/player to demonstrate use of libvorbis as well as
documentation on the Ogg Vorbis audio coding format.

You'll need libogg (distributed separately) to compile this library.
A more comprehensive set of utilities is available in the vorbis-tools
package.

Directory:

./lib  		The source for the libraries, a BSD-license implementation
		of the public domain Ogg Vorbis audio encoding format.

./include       Library API headers

./debian        Rules/spec files for building Debian .deb packages

./doc           Vorbis documentation

./examples	Example code illustrating programmatic use of libvorbis, 
		libvorbisfile and libvorbisenc

./mac 		Codewarrior project files and build tweaks for MacOS.

./macosx 	Project files for MacOS X.

./win32		Win32 projects files and build automation

./vq 		Internal utilities for training/building new LSP/residue 
		and auxiliary codebooks.

CONTACT:

The Ogg homepage is located at 'http://www.xiph.org/ogg/'.
Vorbis's homepage is located at 'http://www.xiph.org/vorbis/'.
Up to date technical documents, contact information, source code and
pre-built utilities may be found there.

The user website for Ogg Vorbis software and audio is http://vorbis.com/

BUILDING FROM TRUNK:

Development source is under subversion revision control at 
https://svn.xiph.org/trunk/vorbis/. You will also need the 
newest versions of autoconf, automake, libtool and pkg-config in
order to compile Vorbis from development source. A configure script
is provided for you in the source tarball distributions.

  [update or checkout latest source]
  ./autogen.sh
  make

and as root if desired:

  make install

This will install the Vorbis libraries (static and shared) into
/usr/local/lib, includes into /usr/local/include and API manpages
(once we write some) into /usr/local/man.

Documentation building requires xsltproc and pdfxmltex.

BUILDING FROM TARBALL DISTRIBUTIONS:

  ./configure
  make

and optionally (as root):
  make install

BUILDING RPMS:

after normal configuring:

  make dist
  rpm -ta libvorbis-<version>.tar.gz

BUILDING ON MACOS 9:

Vorbis on MacOS 9 is built using Metroworks CodeWarrior.  To build it, 
first verify that the Ogg libraries are already built following the
instructions in the Ogg module README.  Open vorbis/mac/libvorbis.mcp,
switch to the "Targets" pane, select everything, and make the project.
Do the same thing to build libvorbisenc.mcp, and libvorbisfile.mcp (in
that order).  In vorbis/mac/Output you will now have both debug and final
versions of Vorbis shared libraries to link your projects against.

To build a project using Ogg Vorbis, add access paths to your
CodeWarrior project for the ogg/include, ogg/mac/Output,
vorbis/include, and vorbis/mac/Output folders.  Be sure that
"interpret DOS and Unix paths" is turned on in your project; it can
be found in the "access paths" pane in your project settings.  Now
simply add the shared libraries you need to your project (OggLib and
VorbisLib at least) and #include "ogg/ogg.h" and "vorbis/codec.h"
wherever you need to access Ogg and Vorbis functionality.

deps/libvorbis/doc/libvorbis/vorbis_synthesis_read.html

<html>

<head>
<title>libvorbis - function - vorbis_synthesis_read</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>libvorbis documentation</p></td>
<td align=right><p class=tiny>libvorbis version 1.3.2 - 20101101</p></td>
</tr>
</table>

<h1>vorbis_synthesis_read</h1>

<p><i>declared in "vorbis/codec.h";</i></p>

<p>This function informs the Vorbis decoder of how many
samples the application used from the last buffer output by
<a href="vorbis_synthesis_pcmout.html">vorbis_synthesis_pcmout</a>.</p>

<table border=0 color=black cellspacing=0 cellpadding=7>
<tr bgcolor=#cccccc>
	<td>
<pre><b>
extern int      vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
</b></pre>
	</td>
</tr>
</table>

<h3>Parameters</h3>
<dl>
<dt><i>v</i></dt>
<dd>The <a href="vorbis_dsp_state.html">vorbis_dsp_state</a> for the
decoder instance.</dd>
<dt><i>samples</i></dt>
<dd>The number of samples the application has used.</dd>
</dl>


<h3>Return Values</h3>
<blockquote>
<li>0 on success.</li>
<li>OV_EINVAL if <i>samples</i> is greater than the number of remaining
samples in the buffer.</li>
</blockquote>
<p>

<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2010 Xiph.Org</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/vorbis/index.html">Ogg Vorbis</a></p></td>
</tr><tr>
<td><p class=tiny>libvorbis documentation</p></td>
<td align=right><p class=tiny>libvorbis version 1.3.2 - 20101101</p></td>
</tr>
</table>


</body>

</html>

deps/libvorbis/doc/vorbisfile/ov_read.html

<html>

<head>
<title>Vorbisfile - function - ov_read</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>

<h1>ov_read()</h1>

<p><i>declared in "vorbis/vorbisfile.h";</i></p>

<p>
   This is the main function used to decode a Vorbis file within a
   loop.  It returns up to the specified number of bytes of decoded PCM audio
   in the requested endianness, signedness, and word size.  If the audio is
   multichannel, the channels are interleaved in the output buffer.
   If the passed in buffer is large, <tt>ov_read()</tt> will not fill
   it; the passed in buffer size is treated as a <em>limit</em> and
   not a request.

<p>The output channels are in stream order and not remapped. Vorbis I
defines channel order as follows:

<ul>
<li>one channel - the stream is monophonic
<li>two channels - the stream is stereo.  channel order: left, right
<li>three channels - the stream is a 1d-surround encoding.  channel order: left,
center, right
<li>four channels - the stream is quadraphonic surround.  channel order: front left,
front right, rear left, rear right
<li>five channels - the stream is five-channel surround.  channel order: front left,
center, front right, rear left, rear right
<li>six channels - the stream is 5.1 surround.  channel order: front left, center, 
front right, rear left, rear right, LFE
<li>seven channels - the stream is 6.1 surround.  channel order: front left, center, 
front right, side left, side right, rear center, LFE
<li>eight channels - the stream is 7.1 surround.  channel order: front left, center, 
front right, side left, side right, rear left, rear right, 
LFE
<li>greater than eight channels - channel use and order is undefined
</ul>

<p>Note that up to this point, the Vorbisfile API could more or less hide the
   multiple logical bitstream nature of chaining from the toplevel
   application if the toplevel application didn't particularly care.
   However, when reading audio back, the application must be aware
   that multiple bitstream sections do not necessarily use the same
   number of channels or sampling rate. <p> <tt>ov_read()</tt> passes
   back the index of the sequential logical bitstream currently being
   decoded (in <tt>*bitstream</tt>) along with the PCM data in order
   that the toplevel application can handle channel and/or sample
   rate changes. This number will be incremented at chaining
   boundaries even for non-seekable streams. For seekable streams, it
   represents the actual chaining index within the physical bitstream.
<p>

<br><br>
<table border=0 color=black cellspacing=0 cellpadding=7>
<tr bgcolor=#cccccc>
	<td>
<pre><b>
long ov_read(<a href="OggVorbis_File.html">OggVorbis_File</a> *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream);
</b></pre>
	</td>
</tr>
</table>

<h3>Parameters</h3>
<dl>
<dt><i>vf</i></dt>
<dd>A pointer to the OggVorbis_File structure--this is used for ALL the externally visible libvorbisfile
functions.</dd>
<dt><i>buffer</i></dt>
<dd>A pointer to an output buffer.  The decoded output is inserted into this buffer.</dd>
<dt><i>length</i></dt>
<dd>Number of bytes to be read into the buffer. Should be the same size as the buffer.  A typical value is 4096.</dd>
<dt><i>bigendianp</i></dt>
<dd>Specifies big or little endian byte packing.  0 for little endian, 1 for b
ig endian.  Typical value is 0.</dd>
<dt><i>word</i></dt>
<dd>Specifies word size.  Possible arguments are 1 for 8-bit samples, or 2 or 
16-bit samples.  Typical value is 2.</dd>
<dt><i>sgned</i></dt>
<dd>Signed or unsigned data.  0 for unsigned, 1 for signed.  Typically 1.</dd>
<dt><i>bitstream</i></dt>
<dd>A pointer to the number of the current logical bitstream.</dd>
</dl>


<h3>Return Values</h3>
<blockquote>
<dl>
<dt>OV_HOLE</dt>
  <dd>indicates there was an interruption in the data.
      <br>(one of: garbage between pages, loss of sync followed by
           recapture, or a corrupt page)</dd>
<dt>OV_EBADLINK</dt>
  <dd>indicates that an invalid stream section was supplied to
      libvorbisfile, or the requested link is corrupt.</dd>
<dt>OV_EINVAL</dt>
  <dd>indicates the initial file headers couldn't be read or 
      are corrupt, or that the initial open call for <i>vf</i> 
      failed.</dd>
<dt>0</dt>
  <dd>indicates EOF</dd>
<dt><i>n</i></dt>
  <dd>indicates actual number of bytes read.  <tt>ov_read()</tt> will
      decode at most one vorbis packet per invocation, so the value
      returned will generally be less than <tt>length</tt>.
</dl>
</blockquote>

<h3>Notes</h3>
<p><b>Typical usage:</b>
<blockquote>
<tt>bytes_read = ov_read(&amp;vf,
buffer, 4096,0,2,1,&amp;current_section)</tt>
</blockquote>

This reads up to 4096 bytes into a buffer, with signed 16-bit
little-endian samples.
</p>



<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2000-2010 Xiph.Org</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/vorbis/">Ogg Vorbis</a></p></td>
</tr><tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>

</body>

</html>

deps/libvorbis/doc/vorbisfile/ov_read_filter.html

<html>

<head>
<title>Vorbisfile - function - ov_read_filter</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>

<h1>ov_read_filter()</h1>

<p><i>declared in "vorbis/vorbisfile.h";</i></p>

<p>
   <tt>ov_read_filter()</tt> is a variant of <a
   href="ov_read.html">ov_read()</a>, the main function used to decode
   a Vorbis file within a loop.  It passes the decoded floating point
   PCM data to the filter specified in the function arguments before
   converting the data to integer output samples. All other aspects of
   its behavior are as with <a href="ov_read.html">ov_read()</a>.
<p>

<br><br>
<table border=0 color=black cellspacing=0 cellpadding=7>
<tr bgcolor=#cccccc>
	<td>
<pre><b>
long ov_read_filter(<a href="OggVorbis_File.html">OggVorbis_File</a> *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream, 
                    void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param);
</b></pre>
	</td>
</tr>
</table>

<h3>Parameters</h3>
<dl>
<dt><i>vf</i></dt>
<dd>A pointer to the OggVorbis_File structure--this is used for ALL the externally visible libvorbisfile
functions.</dd>
<dt><i>buffer</i></dt>
<dd>A pointer to an output buffer.  The decoded output is inserted into this buffer.</dd>
<dt><i>length</i></dt>
<dd>Number of bytes to be read into the buffer. Should be the same size as the buffer.  A typical value is 4096.</dd>
<dt><i>bigendianp</i></dt>
<dd>Specifies big or little endian byte packing.  0 for little endian, 1 for b
ig endian.  Typical value is 0.</dd>
<dt><i>word</i></dt>
<dd>Specifies word size.  Possible arguments are 1 for 8-bit samples, or 2 or 
16-bit samples.  Typical value is 2.</dd>
<dt><i>sgned</i></dt>
<dd>Signed or unsigned data.  0 for unsigned, 1 for signed.  Typically 1.</dd>
<dt><i>bitstream</i></dt>
<dd>A pointer to the number of the current logical bitstream.</dd>
<dt><i>filter</i></dt>
<dd>Filter function to process float PCM data prior to conversion to interleaved integer output.</dd>
<dt><i>filter_param</i></dt>
<dd>Data to pass through to the filter function.</dd>

</dl>


<h3>Return Values</h3>
<blockquote>
<dl>
<dt>OV_HOLE</dt>
  <dd>indicates there was an interruption in the data.
      <br>(one of: garbage between pages, loss of sync followed by
           recapture, or a corrupt page)</dd>
<dt>OV_EBADLINK</dt>
  <dd>indicates that an invalid stream section was supplied to
      libvorbisfile, or the requested link is corrupt.</dd>
<dt>0</dt>
  <dd>indicates EOF</dd>
<dt><i>n</i></dt>
  <dd>indicates actual number of bytes read.  <tt>ov_read()</tt> will
      decode at most one vorbis packet per invocation, so the value
      returned will generally be less than <tt>length</tt>.
</dl>
</blockquote>

<h3>Notes</h3>
<p><b>Typical usage:</b>
<blockquote>
<tt>bytes_read = ov_read_filter(&amp;vf,
buffer, 4096,0,2,1,&amp;current_section, filter, (void *)filter_data_ptr)</tt>
</blockquote>

This reads up to 4096 bytes into a buffer, with signed 16-bit
little-endian samples.  The decoded data is passed to the function <tt>filter</tt> before integer conversiona nd interleave.
</p>



<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2000-2010 Xiph.Org</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/vorbis/">Ogg Vorbis</a></p></td>
</tr><tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>

</body>

</html>

deps/libvorbis/doc/vorbisfile/ov_read_float.html

<html>

<head>
<title>Vorbisfile - function - ov_read_float</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>

<h1>ov_read_float()</h1>

<p><i>declared in "vorbis/vorbisfile.h";</i></p>

<p>
   This is the function used to decode a Vorbis file within a loop, but
   returns samples in native float format instead of in integer formats.
</p><p>
   For information on channel ordering and how ov_read_float() deals with the complex issues 
   of chaining, etc, refer to the documentation for <a href="ov_read.html">ov_read()</a>.
</p>

<br><br>
<table border=0 color=black cellspacing=0 cellpadding=7>
<tr bgcolor=#cccccc>
	<td>
<pre><b>
long ov_read_float(<a href="OggVorbis_File.html">OggVorbis_File</a> *vf, float ***pcm_channels, int samples, int *bitstream);
</b></pre>
	</td>
</tr>
</table>

<h3>Parameters</h3>
<dl>
<dt><i>vf</i></dt>
<dd>A pointer to the OggVorbis_File structure--this is used for ALL the externally visible vorbisfile
functions.</dd>
<dt><i>pcm_channels</i></dt>
<dd>A pointer to an output buffer.  The pointer will be set to the decoded output buffer.</dd>
<dt><i>samples</i></dt>
<dd>Maximum number of decoded samples to produce.</dd>
<dt><i>bitstream</i></dt>
<dd>A pointer to the number of the current logical bitstream.</dd>
</dl>


<h3>Return Values</h3>
<blockquote>
<dl>
<dt>OV_HOLE</dt>
  <dd>indicates there was an interruption in the data.
      <br>(one of: garbage between pages, loss of sync followed by
           recapture, or a corrupt page)</dd>
<dt>OV_EBADLINK</dt>
  <dd>indicates that an invalid stream section was supplied to
      libvorbisfile, or the requested link is corrupt.</dd>
<dt>OV_EINVAL</dt>
  <dd>indicates the initial file headers couldn't be read or
      are corrupt, or that the initial open call for <i>vf</i> 
      failed.</dd>
<dt>0</dt>
  <dd>indicates EOF</dd>
<dt><i>n</i></dt>
  <dd>indicates actual number of samples read.  <tt>ov_read_float()</tt> will
      decode at most one vorbis packet per invocation, so the value
      returned will generally be less than <tt>length</tt>.
</dl>
</blockquote>

<h3>Notes</h3>
<p><b>Typical usage:</b>
<blockquote>
<tt>float **pcm;
samples_read = ov_read_float(&amp;vf,pcm, 1024, &amp;current_section)</tt>
</blockquote>

This decodes up to 1024 float samples.
</p>

<br>
<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2002 vorbis team</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/vorbis/index.html">Ogg Vorbis</a></p></td>
</tr><tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>


</body>

</html>



deps/libvorbis/doc/vorbisfile/threads.html

<html>

<head>
<title>Vorbisfile - Thread Safety</title>
<link rel=stylesheet href="style.css" type="text/css">
</head>

<body bgcolor=white text=black link="#5555ff" alink="#5555ff" vlink="#5555ff">
<table border=0 width=100%>
<tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>

<h1>Thread Safety</h1>

Vorbisfile's libvorbisfile may be used safely in a threading environment
so long as thread access to individual <a
href="OggVorbis_File.html">OggVorbis_File</a> instances is serialized.  
<ul>

<li>Only one thread at a time may enter a function that takes a given <a
href="OggVorbis_File.html">OggVorbis_File</a> instance, even if the
functions involved appear to be read-only.<p>

<li>Multiple threads may enter
libvorbisfile at a given time, so long as each thread's function calls
are using different <a href="OggVorbis_File.html">OggVorbis_File</a>
instances. <p>

<li>Any one <a
href="OggVorbis_File.html">OggVorbis_File</a> instance may be used safely from multiple threads so long as only one thread at a time is making calls using that instance.<p>
</ul>

<br><br>
<hr noshade>
<table border=0 width=100%>
<tr valign=top>
<td><p class=tiny>copyright &copy; 2000-2010 Xiph.Org</p></td>
<td align=right><p class=tiny><a href="http://www.xiph.org/ogg/vorbis/">Ogg Vorbis</a></p></td>
</tr><tr>
<td><p class=tiny>Vorbisfile documentation</p></td>
<td align=right><p class=tiny>vorbisfile version 1.3.2 - 20101101</p></td>
</tr>
</table>

</body>

</html>

deps/libvorbis/test/write_read.c

/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
 *                                                                  *
 ********************************************************************

 function: utility functions for vorbis codec test suite.
 last mod: $Id: util.c 13293 2007-07-24 00:09:47Z erikd $

 ********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <errno.h>

#include <vorbis/codec.h>
#include <vorbis/vorbisenc.h>

#include "write_read.h"

/* The following function is basically a hacked version of the code in
 * examples/encoder_example.c */
void
write_vorbis_data_or_die (const char *filename, int srate, float q, const float * data, int count, int ch)
{
  FILE * file ;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;
  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  int eos = 0, ret;

  if ((file = fopen (filename, "wb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  /********** Encode setup ************/

  vorbis_info_init (&vi);

  ret = vorbis_encode_init_vbr (&vi,ch,srate,q);
  if (ret) {
    printf ("vorbis_encode_init_vbr return %d\n", ret) ;
    exit (1) ;
  }

  vorbis_comment_init (&vc);
  vorbis_comment_add_tag (&vc,"ENCODER","test/util.c");
  vorbis_analysis_init (&vd,&vi);
  vorbis_block_init (&vd,&vb);

  ogg_stream_init (&os,12345678);

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout (&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin (&os,&header);
    ogg_stream_packetin (&os,&header_comm);
    ogg_stream_packetin (&os,&header_code);

    /* Ensures the audio data will start on a new page. */
    while (!eos){
        int result = ogg_stream_flush (&os,&og);
        if (result == 0)
            break;
        fwrite (og.header,1,og.header_len,file);
        fwrite (og.body,1,og.body_len,file);
    }

  }

  {
    /* expose the buffer to submit data */
    float **buffer = vorbis_analysis_buffer (&vd,count);
    int i;

    for(i=0;i<ch;i++)
      memcpy (buffer [i], data, count * sizeof (float)) ;

    /* tell the library how much we actually submitted */
    vorbis_analysis_wrote (&vd,count);
    vorbis_analysis_wrote (&vd,0);
  }

  while (vorbis_analysis_blockout (&vd,&vb) == 1) {
    vorbis_analysis (&vb,NULL);
    vorbis_bitrate_addblock (&vb);

    while (vorbis_bitrate_flushpacket (&vd,&op)) {
      ogg_stream_packetin (&os,&op);

      while (!eos) {
          int result = ogg_stream_pageout (&os,&og);
          if (result == 0)
              break;
          fwrite (og.header,1,og.header_len,file);
          fwrite (og.body,1,og.body_len,file);

          if (ogg_page_eos (&og))
              eos = 1;
      }
    }
  }

  ogg_stream_clear (&os);
  vorbis_block_clear (&vb);
  vorbis_dsp_clear (&vd);
  vorbis_comment_clear (&vc);
  vorbis_info_clear (&vi);

 fclose (file) ;
}

/* The following function is basically a hacked version of the code in
 * examples/decoder_example.c */
void
read_vorbis_data_or_die (const char *filename, int srate, float * data, int count)
{
  ogg_sync_state   oy;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;

  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  FILE *file;
  char *buffer;
  int  bytes;
  int eos = 0;
  int i;
  int read_total = 0 ;

  if ((file = fopen (filename, "rb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  ogg_sync_init (&oy);

  {
    /* fragile!  Assumes all of our headers will fit in the first 8kB,
       which currently they will */
    buffer = ogg_sync_buffer (&oy,8192);
    bytes = fread (buffer,1,8192,file);
    ogg_sync_wrote (&oy,bytes);

    if(ogg_sync_pageout (&oy,&og) != 1) {
      if(bytes < 8192) {
        printf ("Out of data.\n") ;
          goto done_decode ;
      }

      fprintf (stderr,"Input does not appear to be an Ogg bitstream.\n");
      exit (1);
    }

    ogg_stream_init (&os,ogg_page_serialno(&og));

    vorbis_info_init (&vi);
    vorbis_comment_init (&vc);
    if (ogg_stream_pagein (&os,&og) < 0) {
      fprintf (stderr,"Error reading first page of Ogg bitstream data.\n");
      exit (1);
    }

    if (ogg_stream_packetout(&os,&op) != 1) {
      fprintf (stderr,"Error reading initial header packet.\n");
      exit (1);
    }

    if (vorbis_synthesis_headerin (&vi,&vc,&op) < 0) {
      fprintf (stderr,"This Ogg bitstream does not contain Vorbis "
          "audio data.\n");
      exit (1);
    }

    i = 0;
    while ( i < 2) {
      while (i < 2) {

        int result = ogg_sync_pageout (&oy,&og);
        if(result == 0)
          break;
        if(result==1) {
          ogg_stream_pagein(&os,&og);

          while (i < 2) {
            result = ogg_stream_packetout (&os,&op);
            if (result == 0) break;
            if (result < 0) {
              fprintf (stderr,"Corrupt secondary header.  Exiting.\n");
              exit(1);
            }
            vorbis_synthesis_headerin (&vi,&vc,&op);
            i++;
          }
        }
      }

      buffer = ogg_sync_buffer (&oy,4096);
      bytes = fread (buffer,1,4096,file);
      if (bytes == 0 && i < 2) {
        fprintf (stderr,"End of file before finding all Vorbis headers!\n");
        exit (1);
      }

      ogg_sync_wrote (&oy,bytes);
    }

    if (vi.rate != srate) {
      printf ("\n\nError : File '%s' has sample rate of %ld when it should be %d.\n\n", filename, vi.rate, srate);
      exit (1) ;
    }

    vorbis_synthesis_init (&vd,&vi);
    vorbis_block_init (&vd,&vb);

    while(!eos) {
      while (!eos) {
        int result = ogg_sync_pageout (&oy,&og);
        if (result == 0)
          break;
        if (result < 0) {
          fprintf (stderr,"Corrupt or missing data in bitstream; "
                   "continuing...\n");
        } else {
          ogg_stream_pagein (&os,&og);
          while (1) {
            result = ogg_stream_packetout (&os,&op);

            if (result == 0)
              break;
            if (result < 0) {
              /* no reason to complain; already complained above */
            } else {
              float **pcm;
              int samples;

              if (vorbis_synthesis (&vb,&op) == 0)
                vorbis_synthesis_blockin(&vd,&vb);
              while ((samples = vorbis_synthesis_pcmout (&vd,&pcm)) > 0 && read_total < count) {
                int bout = samples < count ? samples : count;
                bout = read_total + bout > count ? count - read_total : bout;

                memcpy (data + read_total, pcm[0], bout * sizeof (float)) ;

                vorbis_synthesis_read (&vd,bout);
                read_total += bout ;
              }
            }
          }

          if (ogg_page_eos (&og)) eos = 1;
        }
      }

      if (!eos) {
        buffer = ogg_sync_buffer (&oy,4096);
        bytes = fread (buffer,1,4096,file);
        ogg_sync_wrote (&oy,bytes);
        if (bytes == 0) eos = 1;
      }
    }

    ogg_stream_clear (&os);

    vorbis_block_clear (&vb);
    vorbis_dsp_clear (&vd);
    vorbis_comment_clear (&vc);
    vorbis_info_clear (&vi);
  }
done_decode:

  /* OK, clean up the framer */
  ogg_sync_clear (&oy);

  fclose (file) ;
}

deps/libvorbis/test/write_read.h

/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
 *                                                                  *
 ********************************************************************

 function: utility functions for vorbis codec test suite.
 last mod: $Id: util.c 13293 2007-07-24 00:09:47Z erikd $

 ********************************************************************/

/* Write supplied data to an Ogg/Vorbis file with specified filename at
 * specified sample rate. Assumes a single channel of audio. */
void write_vorbis_data_or_die (const char *filename, int srate, float q,
                               const float * data, int count, int ch) ;

/* Read given Ogg/Vorbis file into data specified data array. This
 * function is basically the inverse of the one above. Again, assumes
 * a single channel of audio. */
void read_vorbis_data_or_die (const char *filename, int srate,
                        float * data, int count) ;

deps/libvorbis/win32/VS2005/README

libvorbis has libogg as a dependency, you need to have libogg
compiled beforehand.

Lets say you have libogg and libvorbis in the same directory:

libogg-1.1.3 
libvorbis-1.2.0

Because there is no automatic library detection you have to,
either:

1. Rename libogg-1.1.3 to libogg

2. Open libogg.vsprops with a text editor (even notepad.exe
will suffice) and see if LIBOGG_VERSION is set to the correct
version, in this case "1.1.3"

deps/libvorbis/win32/VS2008/README

libvorbis has libogg as a dependency, you need to have libogg
compiled beforehand.

Lets say you have libogg and libvorbis in the same directory:

libogg-1.1.3 
libvorbis-1.2.0

Because there is no automatic library detection you have to,
either:

1. Rename libogg-1.1.3 to libogg

2. Open libogg.vsprops with a text editor (even notepad.exe
will suffice) and see if LIBOGG_VERSION is set to the correct
version, in this case "1.1.3"

deps/libvorbis/win32/VS2010/README

libvorbis has libogg as a dependency, you need to have libogg
compiled beforehand.

Lets say you have libogg and libvorbis in the same directory:

libogg-1.1.3 
libvorbis-1.2.0

Because there is no automatic library detection you have to,
either:

1. Rename libogg-1.1.3 to libogg

2. Open libogg.props with a text editor (even notepad.exe
will suffice) and see if LIBOGG_VERSION is set to the correct
version, in this case "1.1.3"

deps/mozilla/README.txt

SpiderMonkey for Oolite

This repository contains the source code distribution for Firefox 4.0, with
the parts not needed for SpiderMonkey removed, and no code history. There are
no other changes. This corresponds closely to the SpiderMonkey 1.8.5 stand-
alone release.

deps/mozilla/js/jsd/README

js/jsd contains code for debugging support for the C-based JavaScript engine 
in js/src.  jsd_xpc.cpp provides an XPCOM binding for the library.

js/jsd/jsdb is a console debugger using only native code (see README in that 
directory.)  This debugger is no longer being actively developed, though it
should work.

deps/mozilla/js/src/README.html

<!-- ***** BEGIN LICENSE BLOCK *****
   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
   -
   - The contents of this file are subject to the Mozilla Public License Version
   - 1.1 (the "License"); you may not use this file except in compliance with
   - the License. You may obtain a copy of the License at
   - http://www.mozilla.org/MPL/
   -
   - Software distributed under the License is distributed on an "AS IS" basis,
   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   - for the specific language governing rights and limitations under the
   - License.
   - 
   - The Original Code is Mozilla Communicator client code, released
   - March 31, 1998.
   - 
   - The Initial Developer of the Original Code is
   - Netscape Communications Corporation.
   - Portions created by the Initial Developer are Copyright (C) 1998-1999
   - the Initial Developer. All Rights Reserved.
   - 
   - Contributor(s):
   - 
   - Alternatively, the contents of this file may be used under the terms of
   - either of the GNU General Public License Version 2 or later (the "GPL"),
   - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   - in which case the provisions of the GPL or the LGPL are applicable instead
   - of those above. If you wish to allow use of your version of this file only
   - under the terms of either the GPL or the LGPL, and not to allow others to
   - use your version of this file under the terms of the MPL, indicate your
   - decision by deleting the provisions above and replace them with the notice
   - and other provisions required by the GPL or the LGPL. If you do not delete
   - the provisions above, a recipient may use your version of this file under
   - the terms of any one of the MPL, the GPL or the LGPL.
   -
   - ***** END LICENSE BLOCK ***** -->
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <meta http-equiv="Refresh"
	 content="0;URL=http://developer.mozilla.org/en/docs/SpiderMonkey">
   <title>SpiderMonkey README</title>
</head>
<body>

<h1>SpiderMonkey README</h1>

<p>See the
<a href="http://developer.mozilla.org/en/docs/SpiderMonkey">SpiderMonkey
pages</a> on the Mozilla Developer Center</a>.

</body>
</html>

deps/mozilla/js/src/ctypes/libffi/README

Status
======

libffi-3.0.10 was released on XXXXXXXXXX, 2010. Check the libffi web
page for updates: <URL:http://sourceware.org/libffi/>.


What is libffi?
===============

Compilers for high level languages generate code that follow certain
conventions. These conventions are necessary, in part, for separate
compilation to work. One such convention is the "calling
convention". The "calling convention" is essentially a set of
assumptions made by the compiler about where function arguments will
be found on entry to a function. A "calling convention" also specifies
where the return value for a function is found.

Some programs may not know at the time of compilation what arguments
are to be passed to a function. For instance, an interpreter may be
told at run-time about the number and types of arguments used to call
a given function. Libffi can be used in such programs to provide a
bridge from the interpreter program to compiled code.

The libffi library provides a portable, high level programming
interface to various calling conventions. This allows a programmer to
call any function specified by a call interface description at run
time.  

FFI stands for Foreign Function Interface.  A foreign function
interface is the popular name for the interface that allows code
written in one language to call code written in another language. The
libffi library really only provides the lowest, machine dependent
layer of a fully featured foreign function interface. A layer must
exist above libffi that handles type conversions for values passed
between the two languages.


Supported Platforms
===================

Libffi has been ported to many different platforms.
For specific configuration details and testing status, please
refer to the wiki page here:

 http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.10

At the time of release, the following basic configurations have been
tested:

|--------------+------------------|
| Architecture | Operating System |
|--------------+------------------|
| Alpha        | Linux            |
| Alpha        | Tru64            |
| ARM          | Linux            |
| AVR32        | Linux            |
| HPPA         | HPUX             |
| IA-64        | Linux            |
| MIPS         | IRIX             |
| MIPS         | Linux            |
| MIPS64       | Linux            |
| PowerPC      | Linux            |
| PowerPC      | Mac OSX          |
| PowerPC      | FreeBSD          |
| PowerPC64    | Linux            |
| S390         | Linux            |
| S390X        | Linux            |
| SPARC        | Linux            |
| SPARC        | Solaris          |
| SPARC64      | Linux            |
| SPARC64      | FreeBSD          |
| X86          | FreeBSD          |
| X86          | kFreeBSD         |
| X86          | Linux            |
| X86          | Mac OSX          |
| X86          | OpenBSD          |
| X86          | OS/2             |
| X86          | Solaris          |
| X86          | Windows/Cygwin   |
| X86          | Windows/MingW    |
| X86-64       | FreeBSD          |
| X86-64       | Linux            |
| X86-64       | OpenBSD          |
| X86-64       | Windows/MingW    |
|--------------+------------------|

Please send additional platform test results to
libffi-discuss@sourceware.org and feel free to update the wiki page
above.

Installing libffi
=================

First you must configure the distribution for your particular
system. Go to the directory you wish to build libffi in and run the
"configure" program found in the root directory of the libffi source
distribution.

You may want to tell configure where to install the libffi library and
header files. To do that, use the --prefix configure switch.  Libffi
will install under /usr/local by default. 

If you want to enable extra run-time debugging checks use the the
--enable-debug configure switch. This is useful when your program dies
mysteriously while using libffi. 

Another useful configure switch is --enable-purify-safety. Using this
will add some extra code which will suppress certain warnings when you
are using Purify with libffi. Only use this switch when using 
Purify, as it will slow down the library.

It's also possible to build libffi on Windows platforms with
Microsoft's Visual C++ compiler.  In this case, use the msvcc.sh
wrapper script during configuration like so:

path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"

For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
You may also need to specify --build appropriately. When building with MSVC
under a MingW environment, you may need to remove the line in configure
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
present in MingW, and is not required when using MingW-style paths.)

Configure has many other options. Use "configure --help" to see them all.

Once configure has finished, type "make". Note that you must be using
GNU make.  You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.

To ensure that libffi is working as advertised, type "make check".
This will require that you have DejaGNU installed.

To install the library and header files, type "make install".


History
=======

See the ChangeLog files for details.

3.0.10 ???-??-??
        Fix the N64 build on mips-sgi-irix6.5.
	Testsuite fixes for Tru64 Unix.
	Enable builds with Microsoft's compiler.
	Enable x86 builds with Sun's compiler.

3.0.9 Dec-31-09
        Add AVR32 and win64 ports.  Add ARM softfp support.
	Many fixes for AIX, Solaris, HP-UX, *BSD.
	Several PowerPC and x86-64 bug fixes.
	Build DLL for windows.

3.0.8 Dec-19-08
        Add *BSD, BeOS, and PA-Linux support.

3.0.7 Nov-11-08
        Fix for ppc FreeBSD.
	(thanks to Andreas Tobler)

3.0.6 Jul-17-08
        Fix for closures on sh.
	Mark the sh/sh64 stack as non-executable.
	(both thanks to Kaz Kojima)

3.0.5 Apr-3-08
        Fix libffi.pc file.
	Fix #define ARM for IcedTea users.
	Fix x86 closure bug.

3.0.4 Feb-24-08
        Fix x86 OpenBSD configury.

3.0.3 Feb-22-08
        Enable x86 OpenBSD thanks to Thomas Heller, and
	x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
	Clean up test instruction in README.

3.0.2 Feb-21-08
        Improved x86 FreeBSD support.
	Thanks to Björn König.

3.0.1 Feb-15-08
        Fix instruction cache flushing bug on MIPS.
	Thanks to David Daney.

3.0.0 Feb-15-08
        Many changes, mostly thanks to the GCC project.
	Cygnus Solutions is now Red Hat.

  [10 years go by...]

1.20 Oct-5-98
	Raffaele Sena produces ARM port.

1.19 Oct-5-98
	Fixed x86 long double and long long return support.
	m68k bug fixes from Andreas Schwab.
	Patch for DU assembler compatibility for the Alpha from Richard
	Henderson.

1.18 Apr-17-98
	Bug fixes and MIPS configuration changes.

1.17 Feb-24-98
	Bug fixes and m68k port from Andreas Schwab. PowerPC port from
	Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.

1.16 Feb-11-98
	Richard Henderson produces Alpha port.

1.15 Dec-4-97
	Fixed an n32 ABI bug. New libtool, auto* support.

1.14 May-13-97
	libtool is now used to generate shared and static libraries.
	Fixed a minor portability problem reported by Russ McManus
	<mcmanr@eq.gs.com>.

1.13 Dec-2-96
	Added --enable-purify-safety to keep Purify from complaining
	about certain low level code.
	Sparc fix for calling functions with < 6 args.
	Linux x86 a.out fix.

1.12 Nov-22-96
	Added missing ffi_type_void, needed for supporting void return 
	types. Fixed test case for non MIPS machines. Cygnus Support 
	is now Cygnus Solutions. 

1.11 Oct-30-96
	Added notes about GNU make.

1.10 Oct-29-96
	Added configuration fix for non GNU compilers.

1.09 Oct-29-96
	Added --enable-debug configure switch. Clean-ups based on LCLint 
	feedback. ffi_mips.h is always installed. Many configuration 
	fixes. Fixed ffitest.c for sparc builds.

1.08 Oct-15-96
	Fixed n32 problem. Many clean-ups.

1.07 Oct-14-96
	Gordon Irlam rewrites v8.S again. Bug fixes.

1.06 Oct-14-96
	Gordon Irlam improved the sparc port. 

1.05 Oct-14-96
	Interface changes based on feedback.

1.04 Oct-11-96
	Sparc port complete (modulo struct passing bug).

1.03 Oct-10-96
	Passing struct args, and returning struct values works for
	all architectures/calling conventions. Expanded tests.

1.02 Oct-9-96
	Added SGI n32 support. Fixed bugs in both o32 and Linux support.
	Added "make test".

1.01 Oct-8-96
	Fixed float passing bug in mips version. Restructured some
	of the code. Builds cleanly with SGI tools.

1.00 Oct-7-96
	First release. No public announcement.


Authors & Credits
=================

libffi was originally written by Anthony Green <green@redhat.com>.

The developers of the GNU Compiler Collection project have made
innumerable valuable contributions.  See the ChangeLog file for
details.

Some of the ideas behind libffi were inspired by Gianni Mariani's free
gencall library for Silicon Graphics machines.

The closure mechanism was designed and implemented by Kresten Krab
Thorup.

Major processor architecture ports were contributed by the following
developers:

alpha		Richard Henderson
arm		Raffaele Sena
cris		Simon Posnjak, Hans-Peter Nilsson
frv		Anthony Green
ia64		Hans Boehm
m32r		Kazuhiro Inaoka
m68k		Andreas Schwab
mips		Anthony Green, Casey Marshall
mips64		David Daney
pa		Randolph Chung, Dave Anglin, Andreas Tobler
powerpc		Geoffrey Keating, Andreas Tobler, 
			 David Edelsohn, John Hornkvist
powerpc64	Jakub Jelinek
s390		Gerhard Tonn, Ulrich Weigand
sh		Kaz Kojima
sh64		Kaz Kojima
sparc		Anthony Green, Gordon Irlam
x86		Anthony Green, Jon Beniston
x86-64		Bo Thorsen

Jesper Skov and Andrew Haley both did more than their fair share of
stepping through the code and tracking down bugs.

Thanks also to Tom Tromey for bug fixes, documentation and
configuration help.

Thanks to Jim Blandy, who provided some useful feedback on the libffi
interface.

Andreas Tobler has done a tremendous amount of work on the testsuite.

Alex Oliva solved the executable page problem for SElinux.

The list above is almost certainly incomplete and inaccurate.  I'm
happy to make corrections or additions upon request.

If you have a problem, or have found a bug, please send a note to
green@redhat.com.

deps/mozilla/js/src/editline/README

The files in this directory provide simple line-editing and history
support for the standalone javascript engine, through the 'editline'
library.

editline has only been enabled for those platforms on which it is
known to build; to try it on a different platform, define JS_EDITLINE
before building.  Line editing (and js.c) is not a supported feature
of the javascript library, so your mileage my vary.

The editline API is a compatible subset of the FSF readline API; if
you have readline installed and would like to link to that instead,
define JS_READLINE.  Note that the readline library is distributed
under the GPL, so any resulting binaries are not legally
distributable.

The editline files used here have been modified to work with the js
build system and to quiet some compiler warnings, and also to remove
filename-completion support.

If anyone knows of a more recent version of these files, or a site on
which they are being maintained, please let me know!

Mike McCabe, mccabe@netscape.com


The original README file distributed with the editline library follows.



This is a line-editing library.  It can be linked into almost any
program to provide command-line editing and recall.

It is call-compatible with the FSF readline library, but it is a
fraction of the size (and offers fewer features).  It does not use
standard I/O.  It is distributed under a "C News-like" copyright.

Configuration is done in the Makefile.  Type "make testit" to get
a small slow shell for testing.

An earlier version was distributed with Byron's rc.  Principal
changes over that version include:
	Faster.
	Is eight-bit clean (thanks to brendan@cs.widener.edu)
	Written in K&R C, but ANSI compliant (gcc all warnings)
	Propagates EOF properly; rc trip test now passes
	Doesn't need or use or provide memmove.
	More robust
	Calling sequence changed to be compatible with readline.
	Test program, new manpage, better configuration
	More system-independent; includes Unix and OS-9 support.

This contains some changes since the posting to comp.sources.misc:
	Bugfix for completion on absolute pathnames.
	Better handling of M-n versus showing raw 8bit chars.
	Better signal handling.
	Now supports termios/termio/sgttyb ioctl's.
	Add M-m command to toggle how 8bit data is displayed.

There is one known bug:
	History-searching redraws the line wrong if the text
	retrieved is shorter then the prompt.

Enjoy,
	Rich $alz
	<rsalz@osf.org>

 Copyright 1992,1993 Simmule Turner and Rich Salz.  All rights reserved.

 This software is not subject to any license of the American Telephone
 and Telegraph Company or of the Regents of the University of California.

 Permission is granted to anyone to use this software for any purpose on
 any computer system, and to alter it and redistribute it freely, subject
 to the following restrictions:
 1. The authors are not responsible for the consequences of use of this
    software, no matter how awful, even if they arise from flaws in it.
 2. The origin of this software must not be misrepresented, either by
    explicit claim or by omission.  Since few users ever read sources,
    credits must appear in the documentation.
 3. Altered versions must be plainly marked as such, and must not be
    misrepresented as being the original software.  Since few users
    ever read sources, credits must appear in the documentation.
 4. This notice may not be removed or altered.

deps/mozilla/js/src/jit-test/README

JS Trace Test Suite

* PURPOSE

This is a test suite for testing TraceMonkey. All tests are run in the JS shell
with tracing enabled (-j).

* REQUIREMENTS

Python 2.5. This is already a standard requirement for building our tree.

* RUNNING THE TESTS

Basic usage:

    python jit_test.py <path-to-js-shell>

The progress bar shows [#tests passed, #tests failed, #tests run] at the left.
If all tests pass, the output is 'PASSED ALL'. The test suite can be interrupted
at any time with Ctrl+C and partial results will be printed.

To run only the basic tests, not including the slow tests:

    python jit_test.py <path-to-js-shell> basic

For more options:

    python jit_test.py -h

* CREATING NEW TESTS

Simply create a JS file under the 'tests/' directory. Most tests should go in
'tests/basic/'.

All tests are run with 'lib/prolog.js' included first on the command line. The
command line also creates a global variable 'libdir' that is set to the path
of the 'lib' directory. To include a file 'foo.js' from the lib directory in a 
test case:

    load(libdir + 'foo.js')

* TEST METALINES

The first line of a test case can contain a special comment controlling how the
test is run. For example:

    // |jit-test| allow-oom;

The general format in EBNF is:

    metaline  ::= cookie { item ";" }
    cookie    ::= "|jit-test|"
    item      ::= flag | attribute

    flag      ::= "slow" | "allow-oom"

    attribute ::= name ":" value
    name      ::= "TMFLAGS" | "error"
    value     ::= <string>

The metaline may appear anywhere in the first line of the file: this allows it
to be placed inside any kind of comment.

The meaning of the items:

    slow         Test runs slowly. Do not run if the --no-slow option is given.
    allow-oom    If the test runs out of memory, it counts as passing.
    valgrind     Run test under valgrind.

    error        The test should be considered to pass iff it throws the
                 given JS exception.
    TMFLAGS      Set the environment variable TMFLAGS to the given value.

* END

deps/mozilla/js/src/jit-test/tests/basic/testIncDecReadOnly.js

var r;
Object.defineProperty(this, "x", {value: 0, writable: false});

for (var a = 0; a < 10; ++a)
    r = ++x;
assertEq(x, 0);
assertEq(r, 1);

for (var a = 0; a < 10; ++a)
    r = --x;
assertEq(x, 0);
assertEq(r, -1);

for (var a = 0; a < 10; ++a)
    r = x++;
assertEq(x, 0);
assertEq(r, 0);

for (var a = 0; a < 10; ++a)
    r = x--;
assertEq(x, 0);
assertEq(r, 0);

deps/mozilla/js/src/jit-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js

for (var i = 0; i < 5; ++i) {
    var o = {}
    Object.defineProperty(o, 'x', { value:"cow", writable:false });
    var r = o.watch('x', function() {});
    assertEq(r, undefined);
    o.x = 4;
}

deps/mozilla/js/src/jsapi-tests/README

=== JSAPI Test Suite

The tests in this directory exercise the JSAPI.


--- Building and running the tests

If you built JS, you already built the tests.

If you did `make check` in your JS objdir, you already ran them.

The tests are built by default when you build JS. All the tests are compiled
into a single binary named jsapi-tests. They all run in a single process.

To run the tests in a debugger:

    cd $OBJDIR/jsapi-tests
    gdb ./jsapi-tests


--- Creating new tests

 1. You can either add to an existing test*.cpp file or make a new one.
    Copy an existing test and replace the body with your test code.
    The test harness provides `cx`, `rt`, and `global` for your use.

 2. If you made a new .cpp file, add it to the CPPSRCS list in Makefile.in.


--- Writing test code

Here is a sample test:

    #include "tests.h"

    BEGIN_TEST(testIntString_bug515273)
    {
        jsval v;
        EVAL("'42';", &v);

        JSString *str = JSVAL_TO_STRING(v);
        const char *bytes = JS_GetStringBytes(str);
        CHECK(strcmp(bytes, "42") == 0);
        return true;
    }
    END_TEST(testIntString_bug515273)

The BEGIN_TEST and END_TEST macros bracket each test. By convention, the test
name is <testFilename>_<detail>. (The above test is in testIntString.cpp.)

The curly braces are required. This block is the body of a C++ member function
that returns JSBool. The test harness calls this member function
automatically. If the function returns true, the test passes. False, it fails.

JSAPI tests often need extra global C/C++ code: a JSClass, a getter or setter
function, a resolve hook. Put these before the BEGIN_TEST macro.

The body of the test can use these member variables and macros, defined in
tests.h:

    JSRuntime *rt;
    JSContext *cx;
    JSObject *global;

        The test framework creates these fresh for each test. The default
        environment has reasonable default settings, including
        JSOPTION_VAROBJFIX, JSOPTION_JIT, a global object of a class with
        JSCLASS_GLOBAL_FLAGS, and an error reporter that prints to stderr.
        See also "Custom test setup" below.

    EXEC(const char *code);

        Execute some JS code in global scope, using JS_EvaluateScript. Return
        false if that fails. (This means that if the code throws an uncaught JS
        exception, the test fails.)

    EVAL(const char *code, jsval *vp);

        Same as EXEC, but store the result value in *vp.

    CHECK(bool cond);

        If the condition is not true, print an error message and return false,
        failing the test.

    CHECK_SAME(jsval a, jsval b);

        If a and b are different values, print an error message and return
        false, failing the test.

        This is like CHECK(sameValue(a, b)) but with a more detailed error
        message. See sameValue below.

    bool knownFail;

        Set this to true if your test is known to fail. The test runner will
        print a TEST-KNOWN-FAIL line rather than a TEST-UNEXPECTED-FAIL
        line. This way you can check in a test illustrating a bug ahead of the
        fix.

        If your test actually crashes the process or triggers an assertion,
        this of course will not help, so you should add something like

            knownFail = true;  // see bug 123456
            return false;  // the code below crashes!

        as the first two lines of the test.

    bool isNegativeZero(jsval v);
    bool isNaN(jsval v);

        Self-explanatory.

    bool sameValue(jsval v1, jsval v2);

        True if v1 and v2 are the same value according to the ES5 SameValue()
        function, to wit:

        SameValue(NaN, NaN) is true.
        SameValue(-0, 0) is false.
        Otherwise SameValue(a, b) iff a === b.

And see class jsvalRoot, also defined in tests.h.


--- Custom test setup

Before executing each test, the test framework calls the tests' init() member
function, which populates the rt, cx, and global member variables.

A test can customize the test setup process by overloading virtual member
functions, like this:

    JSClass globalClassWithResolve = { ... };

    BEGIN_TEST(testGlobalResolveHook)
        {
            jsvalRoot v;
            EVAL("v", v.addr());
            CHECK_SAME(v, JSVAL_VOID);
            return true;
        }

        // Other class members can go here.

        // This one overloads a base-class method.
        virtual JSClass *getGlobalJSClass() {
            return &globalClassWithResolve;
        }
    END_TEST(testGlobalResolveHook)

The overloadable member functions are:

    virtual bool init();
    virtual void uninit();
    virtual JSRuntime * createRuntime();
    virtual JSContext * createContext();
    virtual JSClass * getGlobalClass();
    virtual JSObject * createGlobal();

deps/mozilla/js/src/jsapi-tests/testThreadGC.cpp

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sw=4 et tw=99:
 */

#ifdef JS_THREADSAFE

#include "tests.h"
#include "prthread.h"

#include "jscntxt.h"

/*
 * We test that if a GC callback cancels the GC on a child thread the GC can
 * still proceed on the main thread even if the child thread continue to
 * run uninterrupted.
 */

struct SharedData {
    enum ChildState {
        CHILD_STARTING,
        CHILD_RUNNING,
        CHILD_DONE,
        CHILD_ERROR
    };

    JSRuntime   *const runtime;
    PRThread    *const mainThread;
    PRLock      *const lock;
    PRCondVar   *const signal;
    ChildState  childState;
    bool        childShouldStop;
    JSContext   *childContext;

    SharedData(JSRuntime *rt, bool *ok)
      : runtime(rt),
        mainThread(PR_GetCurrentThread()),
        lock(PR_NewLock()),
        signal(lock ? PR_NewCondVar(lock) : NULL),
        childState(CHILD_STARTING),
        childShouldStop(false),
        childContext(NULL)
    {
        JS_ASSERT(!*ok);
        *ok = !!signal;
    }

    ~SharedData() {
        if (signal)
            PR_DestroyCondVar(signal);
        if (lock)
            PR_DestroyLock(lock);
    }
};

static SharedData *shared;

static JSBool
CancelNonMainThreadGCCallback(JSContext *cx, JSGCStatus status)
{
    return status != JSGC_BEGIN || PR_GetCurrentThread() == shared->mainThread;
}

static JSBool
StopChildOperationCallback(JSContext *cx)
{
    bool shouldStop;
    PR_Lock(shared->lock);
    shouldStop = shared->childShouldStop;
    PR_Unlock(shared->lock);
    return !shouldStop;
}

static JSBool
NotifyMainThreadAboutBusyLoop(JSContext *cx, uintN argc, jsval *vp)
{
    PR_Lock(shared->lock);
    JS_ASSERT(shared->childState == SharedData::CHILD_STARTING);
    shared->childState = SharedData::CHILD_RUNNING;
    shared->childContext = cx;
    PR_NotifyCondVar(shared->signal);
    PR_Unlock(shared->lock);

    return true;
}

static void
ChildThreadMain(void *arg)
{
    JS_ASSERT(!arg);
    bool error = true;
    JSContext *cx = JS_NewContext(shared->runtime, 8192);
    if (cx) {
        JS_SetOperationCallback(cx, StopChildOperationCallback);
        JSAutoRequest ar(cx);
        JSObject *global = JS_NewCompartmentAndGlobalObject(cx, JSAPITest::basicGlobalClass(),
                                                            NULL);
        if (global) {
            JS_SetGlobalObject(cx, global);
            if (JS_InitStandardClasses(cx, global) &&
                JS_DefineFunction(cx, global, "notify", NotifyMainThreadAboutBusyLoop, 0, 0)) {

                jsval rval;
                static const char code[] = "var i = 0; notify(); for (var i = 0; ; ++i);";
                JSBool ok = JS_EvaluateScript(cx, global, code, strlen(code),
                                              __FILE__, __LINE__, &rval);
                if (!ok && !JS_IsExceptionPending(cx)) {
                    /* Evaluate should only return via the callback cancellation. */
                    error = false;
                }
            }
        }
    }

    PR_Lock(shared->lock);
    shared->childState = error ? SharedData::CHILD_DONE : SharedData::CHILD_ERROR;
    shared->childContext = NULL;
    PR_NotifyCondVar(shared->signal);
    PR_Unlock(shared->lock);

    if (cx)
        JS_DestroyContextNoGC(cx);
}

BEGIN_TEST(testThreadGC_bug590533)
    {
        /*
         * Test the child thread busy running while the current thread calls
         * the GC both with JSRuntime->gcIsNeeded set and unset.
         */
        bool ok = TestChildThread(true);
        CHECK(ok);
        ok = TestChildThread(false);
        CHECK(ok);
        return ok;
    }

    bool TestChildThread(bool setGCIsNeeded)
    {
        bool ok = false;
        shared = new SharedData(rt, &ok);
        CHECK(ok);

        JSGCCallback oldGCCallback = JS_SetGCCallback(cx, CancelNonMainThreadGCCallback);

        PRThread *thread =
            PR_CreateThread(PR_USER_THREAD, ChildThreadMain, NULL,
                            PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (!thread)
            return false;

        PR_Lock(shared->lock);
        while (shared->childState == SharedData::CHILD_STARTING)
            PR_WaitCondVar(shared->signal, PR_INTERVAL_NO_TIMEOUT);
        JS_ASSERT(shared->childState != SharedData::CHILD_DONE);
        ok = (shared->childState == SharedData::CHILD_RUNNING);
        PR_Unlock(shared->lock);

        CHECK(ok);

        if (setGCIsNeeded) {
            /*
             * Use JS internal API to set the GC trigger flag after we know
             * that the child is in a request and is about to run an infinite
             * loop. Then run the GC with JSRuntime->gcIsNeeded flag set.
             */
            js::AutoLockGC lock(rt);
            js::TriggerGC(rt);
        }

        JS_GC(cx);

        PR_Lock(shared->lock);
        shared->childShouldStop = true;
        while (shared->childState == SharedData::CHILD_RUNNING) {
            JS_TriggerOperationCallback(shared->childContext);
            PR_WaitCondVar(shared->signal, PR_INTERVAL_NO_TIMEOUT);
        }
        JS_ASSERT(shared->childState != SharedData::CHILD_STARTING);
        ok = (shared->childState == SharedData::CHILD_DONE);
        PR_Unlock(shared->lock);

        JS_SetGCCallback(cx, oldGCCallback);

        PR_JoinThread(thread);

        delete shared;
        shared = NULL;

        return true;
    }


END_TEST(testThreadGC_bug590533)

#endif

deps/mozilla/js/src/jsapi-tests/testThreads.cpp

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sw=4 et tw=99:
 */

#ifdef JS_THREADSAFE

#include "tests.h"
#include "prthread.h"

struct ThreadData {
    JSRuntime *rt;
    JSObject *obj;
    const char *code;
    bool ok;
};

BEGIN_TEST(testThreads_bug561444)
    {
        const char *code = "<a><b/></a>.b.@c = '';";
        EXEC(code);

        jsrefcount rc = JS_SuspendRequest(cx);
        {
            ThreadData data = {rt, global, code, false};
            PRThread *thread = 
                PR_CreateThread(PR_USER_THREAD, threadMain, &data,
                                PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
            CHECK(thread);
            PR_JoinThread(thread);
            CHECK(data.ok);
        }
        JS_ResumeRequest(cx, rc);
        return true;
    }

    static void threadMain(void *arg) {
        ThreadData *d = (ThreadData *) arg;

        JSContext *cx = JS_NewContext(d->rt, 8192);
        if (!cx)
            return;
        JS_BeginRequest(cx);
        {
            JSAutoEnterCompartment ac;
            jsval v;
            d->ok = ac.enter(cx, d->obj) &&
                    JS_EvaluateScript(cx, d->obj, d->code, strlen(d->code), __FILE__, __LINE__,
                                      &v);
        }
        JS_DestroyContext(cx);
    }
END_TEST(testThreads_bug561444)

const PRUint32 NATIVE_STACK_SIZE = 64 * 1024;
const PRUint32 NATIVE_STACK_HEADROOM = 8 * 1024;

template <class T>
class Repeat {
    size_t n;
    const T &t;

  public:
    Repeat(size_t n, const T &t) : n(n), t(t) {}

    bool operator()() const {
	for (size_t i = 0; i < n; i++)
	    if (!t())
		return false;
	return true;
    }
};

template <class T> Repeat<T> repeat(size_t n, const T &t) { return Repeat<T>(n, t); }

/* Class of callable that does something in n parallel threads. */
template <class T>
class Parallel {
    size_t n;
    const T &t;

    struct pair { const Parallel *self; bool ok; };

    static void threadMain(void *arg) {
	pair *p = (pair *) arg;
	if (!p->self->t())
	    p->ok = false;
    }

  public:
    Parallel(size_t n, const T &t) : n(n), t(t) {}

    bool operator()() const {
	pair p = {this, true};

        PRThread **thread = new PRThread *[n];
	if (!thread)
	    return false;

        size_t i;
        for (i = 0; i < n; i++) {
            thread[i] = PR_CreateThread(PR_USER_THREAD, threadMain, &p, PR_PRIORITY_NORMAL,
                                        PR_LOCAL_THREAD, PR_JOINABLE_THREAD, NATIVE_STACK_SIZE);
            if (thread[i] == NULL) {
                p.ok = false;
                break;
            }
        }
        while (i--)
            PR_JoinThread(thread[i]);

	delete[] thread;
        return p.ok;
    }
};

template <class T> Parallel<T> parallel(size_t n, const T &t) { return Parallel<T>(n, t); }

/* Class of callable that creates a compartment and runs some code in it. */
class eval {
    JSRuntime *rt;
    const char *code;

  public:
    eval(JSRuntime *rt, const char *code) : rt(rt), code(code) {}

    bool operator()() const {
        JSContext *cx = JS_NewContext(rt, 8192);
	if (!cx)
	    return false;

        JS_SetNativeStackQuota(cx, NATIVE_STACK_SIZE - NATIVE_STACK_HEADROOM);
        bool ok = false;
	{
	    JSAutoRequest ar(cx);
	    JSObject *global =
		JS_NewCompartmentAndGlobalObject(cx, JSAPITest::basicGlobalClass(), NULL);
	    if (global) {
		JS_SetGlobalObject(cx, global);
		jsval rval;
		ok = JS_InitStandardClasses(cx, global) &&
		    JS_EvaluateScript(cx, global, code, strlen(code), "", 0, &rval);
	    }
	}
	JS_DestroyContextMaybeGC(cx);
        return ok;
    }
};

BEGIN_TEST(testThreads_bug604782)
{
    jsrefcount rc = JS_SuspendRequest(cx);
    bool ok = repeat(20, parallel(3, eval(rt, "for(i=0;i<1000;i++);")))();
    JS_ResumeRequest(cx, rc);
    CHECK(ok);
    return true;
}
END_TEST(testThreads_bug604782)

BEGIN_TEST(testThreads_bug609103)
{
    const char *code = 
        "var x = {};\n"
        "for (var i = 0; i < 10000; i++)\n"
        "    x = {next: x};\n";

    jsrefcount rc = JS_SuspendRequest(cx);
    bool ok = parallel(2, eval(rt, code))();
    JS_ResumeRequest(cx, rc);
    CHECK(ok);
    return true;
}
END_TEST(testThreads_bug609103)

#endif

deps/mozilla/js/src/metrics/gc/README.txt

Usage:

Requirements:
1) The shell has to be compiled with --enable-gctimer

2) The JS_WANT_GC_SUITE_PRINT flag has to be set to true in jsgc.cpp

Tested with python2.6

deps/mozilla/js/src/tests/ecma/README

ECMA 262 Edition 1

deps/mozilla/js/src/tests/ecma_2/README

ECMA 262 Edition 2

deps/mozilla/js/src/tests/ecma_3/README

ECMA 262 Edition 3

deps/mozilla/js/src/tests/ecma_3_1/README

ECMA 3.1

deps/mozilla/js/src/tests/ecma_5/README

ECMA 5

deps/mozilla/js/src/tests/js1_1/README

JavaScript 1.1

deps/mozilla/js/src/tests/js1_2/README

JavaScript 1.2

deps/mozilla/js/src/tests/js1_3/README

JavaScript 1.3

deps/mozilla/js/src/tests/js1_4/README

JavaScript 1.4

deps/mozilla/js/src/tests/js1_5/README

JavaScript 1.5

deps/mozilla/js/src/tests/js1_6/README

JavaScript 1.6

deps/mozilla/js/src/tests/js1_7/README

JavaScript 1.7

deps/mozilla/js/src/tests/js1_8/README

JavaScript 1.8

deps/mozilla/js/src/tests/js1_8_1/README

JavaScript 1.8.1

deps/mozilla/js/src/tests/js1_8_5/README

JavaScript 1.8.5

Use this suite for tests which require EcmaScript 5 along with features such as
|let|, |yield|

deps/mozilla/js/src/tests/narcissus.README

To run narcissus with jstests.py, change to the js/src/tests/ directory and run
the following command (which excludes tests that are particularly slow):

  python jstests.py -d -j 4 $OBJDIR/njs -x slow-narcissus.txt


Currently, Narcissus is failing a number of tests.  narcissus-failures.txt can
be used to ignore those tests.  Note that narcissus-failures.txt also includes
all of the tests from slow-narcissus.txt.

  python jstests.py -d -j 4 $OBJDIR/njs -x narcissus-failures.txt

deps/mozilla/js/src/tracevis/README

This directory contains TraceVis scripts.


To use TraceVis:

- Currently it can only be used with the JavaScript shell 'js', not within
  Firefox.

- Configure using --enable-tracevis.

- If running your program from the command line, use the -T option, i.e.:

    js -j -T <tracevis-file> foo.js
  
- If running your programs within the interactive shell, use the
  startTraceVis() and stopTraceVis() functions to turn TraceVis recording on
  and off.  startTraceVis() takes an optional parameter which is the name of
  the file to write the TraceVis output to;  if unspecified, the name
  defaults to 'tracevis.dat' in the current directory.

- To view the recorded data in graphical form, run:

    python vis.py <tracevis-file> <png-file>

  The graph will be written to the file <png-file> in PNG format.

- To view some basic data about the recorded data, run:

    python binlog.py <tracevis-file>


Troubleshooting:

- If you get this message when running the python scripts:

    Traceback (most recent call last):
      File "vis.py", line 2, in <module>
        import Image, ImageDraw, ImageFont
        ImportError: No module named Image

  then you need to install libraries from
  http://www.pythonware.com/products/pil/.


TODO list:

- Make the Python scripts more robust, e.g. handle file opening failures
  gracefully.

- Make it usable within Firefox.

deps/mozilla/js/src/v8-dtoa/README

This directory contains V8's fast dtoa conversion code.  The V8 revision
imported was:

   Repository Root: http://v8.googlecode.com/svn
   Repository UUID: ce2b1a6d-e550-0410-aec6-3dcde31c8c00
   Revision: 5322

The function of interest, which is called by SpiderMonkey, is
conversions.cc:DoubleToCString().  This is called from jsnum.cpp to provide a
fast Number.toString(10) implementation.

A great deal of code has been removed from the imported files.  The
remaining code is more or less the bare minimum required to support this
function in a straightforward, standalone manner.

Two related functions in V8 are DoubleToExponentialCString() and
DoubleToPrecisionString(), which can be used to implement
Number.toExponential() and Number.toPrecision().  They have not been imported;
they both call dtoa() and so are unlikely to be noticeably faster than the
existing SpiderMonkey equivalents.

Another related function in V8 is DoubleToRadixCString(), which can be used to
implement Number.toString(base), where base != 10.  This has not been imported;
it may well be faster than SpiderMonkey's implementation, but V8 generates its
own definition of the modulo() function on Win64 and importing this would
require also importing large chunks of the assembler, which is not worthwhile.

Yet another related function in V8 is DoubleToFixedCString(), which can be used
to implement Number.toFixed().  This has not been imported as it was measured
as slower than SpiderMonkey's version.

Comments preceded by the string "MOZ: " indicate places where the code has
been changed significantly from the original code.

deps/mozilla/js/src/vprof/readme.txt

# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http:#www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is [Open Source Virtual Machine.].
#
# The Initial Developer of the Original Code is
# Adobe System Incorporated.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#   Adobe AS3 Team
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****

The two files vprof.h and vprof.cpp implement a simple value-profiling mechanism. By including these two files in avmplus (or any other project), you can value profile data as you wish (currently integers).

Usage:
#include "vprof.h"  // in the source file you want to use it

_vprof (value); 

At the end of the execution, for each probe you'll get the data associated with the probe, such as:

File                                        line    avg     [min : max] total       count
..\..\pcre\pcre_valid_utf8.cpp  182 50222.75916 [0 :    104947] 4036955604  80381  

The probe is defined at line 182 of file pcre_vali_utf8.cpp. It was called 80381 times. The min value of the probe was 0 while its max was 10497 and its average was  50222.75916. The total sum of all values of the probe is 4036955604. Later, I plan to add more options on the spectrum of data among others.

A few typical uses
------------------

To see how many times a given function gets executed do:

void f()
{
    _vprof(1);
    ...
} 

void f()
{
        _vprof(1);
        ...
       if (...) {
           _vprof(1);
           ...
       } else {
           _vprof(1);
           ...
       }
}

Here are a few examples of using the value-profiling utility:

  _vprof (e);
    at the end of program execution, you'll get a dump of the source location of this probe,
    its min, max, average, the total sum of all instances of e, and the total number of times this probe was called. 

  _vprof (x > 0); 
    shows how many times and what percentage of the cases x was > 0, 
    that is the probablitiy that x > 0.
 
 _vprof (n % 2 == 0); 
    shows how many times n was an even number 
    as well as th probablitiy of n being an even number. 
 
 _hprof (n, 4, 1000, 5000, 5001, 10000); 
    gives you the histogram of n over the given 4 bucket boundaries:
        # cases <  1000 
        # cases >= 1000 and < 5000
        # cases >= 5000 and < 5001
        # cases >= 5001 and < 10000
        # cases >= 10000  
 
 _nvprof ("event name", value); 
    all instances with the same name are merged
    so, you can call _vprof with the same event name at difference places
 
 _vprof (e, myProbe);  
    value profile e and call myProbe (void* vprofID) at the profiling point.
    inside the probe, the client has the predefined variables:
    _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers
    _IVAR1, ..., IVAR4      general integer registrs
    _I64VAR1, ..., I64VAR4  general integer64 registrs  
    _DVAR1, ..., _DVAR4     general double registers
    _GENPTR a generic pointer that can be used by the client 
    the number of registers can be changed in vprof.h

Named Events
------------
_nvprof ("event name", value);  
    all instances with the same name are merged
    so, you can call _vprof with the same event name at difference places


Custom Probes
--------------
You can call your own custom probe at the profiling point.
_vprof (v, myProbe);  
   value profile v and call myProbe (void* vprofID) at the profiling point
   inside the probe, the client has the predefined variables:
   _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers
   _IVAR1, ..., IVAR4   general integer registrs
   _I64VAR1, ..., I64VAR4 general integer64 registrs    
   _DVAR1, ..., _DVAR4  general double registers
  the number of registers can be changed in vprof.h
  _GENPTR a generic pointer that can be used for almost anything                

deps/mozilla/js/src/xpconnect/sample/README

xpcsample1.* is a set of files that show a sample of implementing some simple
xpcom classes and relecting them into JavaScript as a chain of properties on the
global object.

xpcsample1.idl declares four interfaces: nsIXPCSample_ClassA,
nsIXPCSample_ClassB, nsIXPCSample_ClassC, and nsIXPCSample_HookerUpper. 'A' has
an integer value (called 'someValue') and a 'B'. 'B' has an integer value and a
'C'. 'C' just has an integer value. nsIXPCSample_HookerUpper just has one method
that when called will attach an instance of 'A' to the global object. 

Confused? This is quite contrived. It will make more sense after examining the
code.

So, this means that after calling the method
nsIXPCSample_HookerUpper::createSampleObjectAtGlobalScope in JavaScript one can
access:

A.someValue, A.B.someValue, and A.B.C.someValue.

see xpcsample.js (or run 'xpcshell xpcsample.js').

The point of all this is to show how to build a hierarchy of native xpcom
objects
with properties and methods reflected into JavaScript. Of course, in real
life these interfaces and native objects would be much more interesting.

The only direct jsapi calls required are those that will 'root' the hierarchy
into the JavaSCript namespace. 'createSampleObjectAtGlobalScope' shows an
example of doing this. 

Most native objects can be satisfactorily reflected using these mechanisms.
However, some fancy stuff might require the extended support found in
nsIXPCScriptable.h. For example, relecting objects that act like constructor
functions, receiving 'finalize' calls on the native object, or reflecting
'dynamically' named properties (i.e. those not declared in xpidl). Native xpcom 
objects that implement nsIXPCScriptable are given much more control over how
they are reflected into JavaScript. There should be few situations where this
additional control is needed.

deps/mozilla/js/src/xpconnect/src/README

see http://www.mozilla.org/scriptable

deps/mozilla/js/src/xpconnect/src/xpcthreadcontext.cpp

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sw=4 et tw=80:
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   John Bandhauer <jband@netscape.com> (original author)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/* Implement global service to track stack of JSContext per thread. */

#include "xpcprivate.h"
#include "XPCWrapper.h"
#include "nsDOMJSUtils.h"
#include "nsIScriptGlobalObject.h"
#include "nsNullPrincipal.h"

/***************************************************************************/

XPCJSContextStack::XPCJSContextStack()
    : mStack(),
      mSafeJSContext(nsnull),
      mOwnSafeJSContext(nsnull)
{
    // empty...
}

XPCJSContextStack::~XPCJSContextStack()
{
    if(mOwnSafeJSContext)
    {
        JS_SetContextThread(mOwnSafeJSContext);
        JS_DestroyContext(mOwnSafeJSContext);
        mOwnSafeJSContext = nsnull;
    }
}

/* readonly attribute PRInt32 count; */
NS_IMETHODIMP
XPCJSContextStack::GetCount(PRInt32 *aCount)
{
    *aCount = mStack.Length();
    return NS_OK;
}

/* JSContext peek (); */
NS_IMETHODIMP
XPCJSContextStack::Peek(JSContext * *_retval)
{
    *_retval = mStack.IsEmpty() ? nsnull : mStack[mStack.Length() - 1].cx;
    return NS_OK;
}

/* JSContext pop (); */
NS_IMETHODIMP
XPCJSContextStack::Pop(JSContext * *_retval)
{
    NS_ASSERTION(!mStack.IsEmpty(), "ThreadJSContextStack underflow");

    PRUint32 idx = mStack.Length() - 1; // The thing we're popping
    NS_ASSERTION(!mStack[idx].frame,
                 "Shouldn't have a pending frame to restore on the context "
                 "we're popping!");

    if(_retval)
        *_retval = mStack[idx].cx;

    mStack.RemoveElementAt(idx);
    if(idx > 0)
    {
        --idx; // Advance to new top of the stack

        XPCJSContextInfo & e = mStack[idx];
        NS_ASSERTION(!e.frame || e.cx, "Shouldn't have frame without a cx!");
        NS_ASSERTION(!e.suspendDepth || e.cx, "Shouldn't have suspendDepth without a cx!");
        if(e.cx)
        {
            if(e.suspendDepth)
            {
                JS_ResumeRequest(e.cx, e.suspendDepth);
                e.suspendDepth = 0;
            }

            if(e.frame)
            {
                // Pop() can be called outside any request for e.cx.
                JSAutoRequest ar(e.cx);
                JS_RestoreFrameChain(e.cx, e.frame);
                e.frame = nsnull;
            }
        }
    }
    return NS_OK;
}

static nsIPrincipal*
GetPrincipalFromCx(JSContext *cx)
{
    nsIScriptContextPrincipal* scp = GetScriptContextPrincipalFromJSContext(cx);
    if(scp)
    {
        nsIScriptObjectPrincipal* globalData = scp->GetObjectPrincipal();
        if(globalData)
            return globalData->GetPrincipal();
    }
    return nsnull;
}

/* void push (in JSContext cx); */
NS_IMETHODIMP
XPCJSContextStack::Push(JSContext * cx)
{
    JS_ASSERT_IF(cx, JS_GetContextThread(cx));
    if(!mStack.AppendElement(cx))
        return NS_ERROR_OUT_OF_MEMORY;
    if(mStack.Length() > 1)
    {
        XPCJSContextInfo & e = mStack[mStack.Length() - 2];
        if(e.cx)
        {
            if(e.cx == cx)
            {
                nsIScriptSecurityManager* ssm = XPCWrapper::GetSecurityManager();
                if(ssm)
                {
                    nsIPrincipal* globalObjectPrincipal =
                        GetPrincipalFromCx(cx);
                    if(globalObjectPrincipal)
                    {
                        nsIPrincipal* subjectPrincipal = ssm->GetCxSubjectPrincipal(cx);
                        PRBool equals = PR_FALSE;
                        globalObjectPrincipal->Equals(subjectPrincipal, &equals);
                        if(equals)
                        {
                            return NS_OK;
                        }
                    }
                }
            }

            {
                // Push() can be called outside any request for e.cx.
                JSAutoRequest ar(e.cx);
                e.frame = JS_SaveFrameChain(e.cx);
            }

            if(!cx)
                e.suspendDepth = JS_SuspendRequest(e.cx);
        }
    }
    return NS_OK;
}

#ifdef DEBUG
JSBool 
XPCJSContextStack::DEBUG_StackHasJSContext(JSContext*  aJSContext)
{
    for(PRUint32 i = 0; i < mStack.Length(); i++)
        if(aJSContext == mStack[i].cx)
            return JS_TRUE;
    return JS_FALSE;
}
#endif

static JSBool
SafeGlobalResolve(JSContext *cx, JSObject *obj, jsid id)
{
    JSBool resolved;
    return JS_ResolveStandardClass(cx, obj, id, &resolved);
}

static void
SafeFinalize(JSContext* cx, JSObject* obj)
{
#ifndef XPCONNECT_STANDALONE
    nsIScriptObjectPrincipal* sop =
        static_cast<nsIScriptObjectPrincipal*>(xpc_GetJSPrivate(obj));
    NS_IF_RELEASE(sop);
#endif
}

static JSClass global_class = {
    "global_for_XPCJSContextStack_SafeJSContext",
#ifndef XPCONNECT_STANDALONE
    JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_GLOBAL_FLAGS,
#else
    0,
#endif
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
    JS_EnumerateStub, SafeGlobalResolve, JS_ConvertStub, SafeFinalize,
    JSCLASS_NO_OPTIONAL_MEMBERS
};

/* attribute JSContext safeJSContext; */
NS_IMETHODIMP
XPCJSContextStack::GetSafeJSContext(JSContext * *aSafeJSContext)
{
    if(!mSafeJSContext)
    {
#ifndef XPCONNECT_STANDALONE
        // Start by getting the principal holder and principal for this
        // context.  If we can't manage that, don't bother with the rest.
        nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
        nsCOMPtr<nsIScriptObjectPrincipal> sop;
        if(principal)
        {
            nsresult rv = principal->Init();
            if(NS_SUCCEEDED(rv))
              sop = new PrincipalHolder(principal);
        }
        if(!sop)
        {
            *aSafeJSContext = nsnull;
            return NS_ERROR_FAILURE;
        }        
#endif /* !XPCONNECT_STANDALONE */
        
        JSRuntime *rt;
        XPCJSRuntime* xpcrt;

        nsXPConnect* xpc = nsXPConnect::GetXPConnect();
        nsCOMPtr<nsIXPConnect> xpcholder(static_cast<nsIXPConnect*>(xpc));

        if(xpc && (xpcrt = xpc->GetRuntime()) && (rt = xpcrt->GetJSRuntime()))
        {
            JSObject *glob;
            mSafeJSContext = JS_NewContext(rt, 8192);
            if(mSafeJSContext)
            {
                // scoped JS Request
                JSAutoRequest req(mSafeJSContext);

                // Because we can run off the main thread, we create an MT
                // global object. Our principal is the unique key.
                JSCompartment *compartment;
                nsresult rv = xpc_CreateMTGlobalObject(mSafeJSContext,
                                                       &global_class,
                                                       principal, &glob,
                                                       &compartment);
                if(NS_FAILED(rv))
                    glob = nsnull;

#ifndef XPCONNECT_STANDALONE
                if(glob)
                {
                    // Make sure the context is associated with a proper compartment
                    // and not the default compartment.
                    JS_SetGlobalObject(mSafeJSContext, glob);

                    // Note: make sure to set the private before calling
                    // InitClasses
                    nsIScriptObjectPrincipal* priv = nsnull;
                    sop.swap(priv);
                    if(!JS_SetPrivate(mSafeJSContext, glob, priv))
                    {
                        // Drop the whole thing
                        NS_RELEASE(priv);
                        glob = nsnull;
                    }
                }

                // After this point either glob is null and the
                // nsIScriptObjectPrincipal ownership is either handled by the
                // nsCOMPtr or dealt with, or we'll release in the finalize
                // hook.
#endif
                if(glob && NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
                {
                    glob = nsnull;
                }

            }
            if(mSafeJSContext && !glob)
            {
                // Destroy the context outside the scope of JSAutoRequest that
                // uses the context in its destructor.
                JS_DestroyContext(mSafeJSContext);
                mSafeJSContext = nsnull;
            }
            // Save it off so we can destroy it later, even if
            // mSafeJSContext has been set to another context
            // via SetSafeJSContext.  If we don't get here,
            // then mSafeJSContext must have been set via
            // SetSafeJSContext, and we're not responsible for
            // destroying the passed-in context.
            mOwnSafeJSContext = mSafeJSContext;
        }
    }

    *aSafeJSContext = mSafeJSContext;
    return mSafeJSContext ? NS_OK : NS_ERROR_UNEXPECTED;
}

NS_IMETHODIMP
XPCJSContextStack::SetSafeJSContext(JSContext * aSafeJSContext)
{
    if(mOwnSafeJSContext &&
       mOwnSafeJSContext == mSafeJSContext &&
       mOwnSafeJSContext != aSafeJSContext)
    {
        JS_DestroyContextNoGC(mOwnSafeJSContext);
        mOwnSafeJSContext = nsnull;
    }

    mSafeJSContext = aSafeJSContext;
    return NS_OK;
}

/***************************************************************************/

PRUintn           XPCPerThreadData::gTLSIndex       = BAD_TLS_INDEX;
PRLock*           XPCPerThreadData::gLock           = nsnull;
XPCPerThreadData* XPCPerThreadData::gThreads        = nsnull;
XPCPerThreadData *XPCPerThreadData::sMainThreadData = nsnull;
void *            XPCPerThreadData::sMainJSThread   = nsnull;

XPCPerThreadData::XPCPerThreadData()
    :   mJSContextStack(new XPCJSContextStack()),
        mNextThread(nsnull),
        mCallContext(nsnull),
        mResolveName(JSID_VOID),
        mResolvingWrapper(nsnull),
        mExceptionManager(nsnull),
        mException(nsnull),
        mExceptionManagerNotAvailable(JS_FALSE),
        mAutoRoots(nsnull)
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
      , mWrappedNativeThreadsafetyReportDepth(0)
#endif
{
    MOZ_COUNT_CTOR(xpcPerThreadData);
    if(gLock)
    {
        nsAutoLock lock(gLock);
        mNextThread = gThreads;
        gThreads = this;
    }
}

void
XPCPerThreadData::Cleanup()
{
    while(mAutoRoots)
        mAutoRoots->Unlink();
    NS_IF_RELEASE(mExceptionManager);
    NS_IF_RELEASE(mException);
    delete mJSContextStack;
    mJSContextStack = nsnull;

    if(mCallContext)
        mCallContext->SystemIsBeingShutDown();
}

XPCPerThreadData::~XPCPerThreadData()
{
    /* Be careful to ensure that both any update to |gThreads| and the
       decision about whether or not to destroy the lock, are done
       atomically.  See bug 557586. */
    PRBool doDestroyLock = PR_FALSE;

    MOZ_COUNT_DTOR(xpcPerThreadData);

    Cleanup();

    // Unlink 'this' from the list of threads.
    if(gLock)
    {
        nsAutoLock lock(gLock);
        if(gThreads == this)
            gThreads = mNextThread;
        else
        {
            XPCPerThreadData* cur = gThreads;
            while(cur)
            {
                if(cur->mNextThread == this)
                {
                    cur->mNextThread = mNextThread;
                    break;
                }
                cur = cur->mNextThread;
            }
        }
        if (!gThreads)
            doDestroyLock = PR_TRUE;
    }

    if(gLock && doDestroyLock)
    {
        PR_DestroyLock(gLock);
        gLock = nsnull;
    }
}

static void
xpc_ThreadDataDtorCB(void* ptr)
{
    XPCPerThreadData* data = (XPCPerThreadData*) ptr;
    if(data)
        delete data;
}

void XPCPerThreadData::TraceJS(JSTracer *trc)
{
#ifdef XPC_TRACK_AUTOMARKINGPTR_STATS
    {
        static int maxLength = 0;
        int length = 0;
        for(AutoMarkingPtr* p = mAutoRoots; p; p = p->GetNext())
            length++;
        if(length > maxLength)
            maxLength = length;
        printf("XPC gc on thread %x with %d AutoMarkingPtrs (%d max so far)\n",
               this, length, maxLength);
    }
#endif

    if(mAutoRoots)
        mAutoRoots->TraceJS(trc);
}

void XPCPerThreadData::MarkAutoRootsAfterJSFinalize()
{
    if(mAutoRoots)
        mAutoRoots->MarkAfterJSFinalize();
}

// static
XPCPerThreadData*
XPCPerThreadData::GetDataImpl(JSContext *cx)
{
    XPCPerThreadData* data;

    if(!gLock)
    {
        gLock = PR_NewLock();
        if(!gLock)
            return nsnull;
    }

    if(gTLSIndex == BAD_TLS_INDEX)
    {
        nsAutoLock lock(gLock);
        // check again now that we have the lock...
        if(gTLSIndex == BAD_TLS_INDEX)
        {
            if(PR_FAILURE ==
               PR_NewThreadPrivateIndex(&gTLSIndex, xpc_ThreadDataDtorCB))
            {
                NS_ERROR("PR_NewThreadPrivateIndex failed!");
                gTLSIndex = BAD_TLS_INDEX;
                return nsnull;
            }
        }
    }

    data = (XPCPerThreadData*) PR_GetThreadPrivate(gTLSIndex);
    if(!data)
    {
        data = new XPCPerThreadData();
        if(!data || !data->IsValid())
        {
            NS_ERROR("new XPCPerThreadData() failed!");
            if(data)
                delete data;
            return nsnull;
        }
        if(PR_FAILURE == PR_SetThreadPrivate(gTLSIndex, data))
        {
            NS_ERROR("PR_SetThreadPrivate failed!");
            delete data;
            return nsnull;
        }
    }

    if(cx && !sMainJSThread && NS_IsMainThread())
    {
        sMainJSThread = cx->thread;

        sMainThreadData = data;

        sMainThreadData->mThread = PR_GetCurrentThread();
    }

    return data;
}

// static
void
XPCPerThreadData::CleanupAllThreads()
{
    // I've questioned the sense of cleaning up other threads' data from the
    // start. But I got talked into it. Now I see that we *can't* do all the
    // cleaup while holding this lock. So, we are going to go to the trouble
    // to copy out the data that needs to be cleaned up *outside* of
    // the lock. Yuk!

    XPCJSContextStack** stacks = nsnull;
    int count = 0;
    int i;

    if(gLock)
    {
        nsAutoLock lock(gLock);

        for(XPCPerThreadData* cur = gThreads; cur; cur = cur->mNextThread)
            count++;

        stacks = (XPCJSContextStack**) new XPCJSContextStack*[count] ;
        if(stacks)
        {
            i = 0;
            for(XPCPerThreadData* cur = gThreads; cur; cur = cur->mNextThread)
            {
                stacks[i++] = cur->mJSContextStack;
                cur->mJSContextStack = nsnull;
                cur->Cleanup();
            }
        }
    }

    if(stacks)
    {
        for(i = 0; i < count; i++)
            delete stacks[i];
        delete [] stacks;
    }

    if(gTLSIndex != BAD_TLS_INDEX)
        PR_SetThreadPrivate(gTLSIndex, nsnull);
}

// static
XPCPerThreadData*
XPCPerThreadData::IterateThreads(XPCPerThreadData** iteratorp)
{
    *iteratorp = (*iteratorp == nsnull) ? gThreads : (*iteratorp)->mNextThread;
    return *iteratorp;
}

NS_IMPL_ISUPPORTS1(nsXPCJSContextStackIterator, nsIJSContextStackIterator)

NS_IMETHODIMP
nsXPCJSContextStackIterator::Reset(nsIJSContextStack *aStack)
{
    NS_ASSERTION(aStack == nsXPConnect::GetXPConnect(),
                 "aStack must be implemented by XPConnect singleton");
    XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    if(!data)
        return NS_ERROR_FAILURE;
    mStack = data->GetJSContextStack()->GetStack();
    if(mStack->IsEmpty())
        mStack = nsnull;
    else
        mPosition = mStack->Length() - 1;

    return NS_OK;
}

NS_IMETHODIMP
nsXPCJSContextStackIterator::Done(PRBool *aDone)
{
    *aDone = !mStack;
    return NS_OK;
}

NS_IMETHODIMP
nsXPCJSContextStackIterator::Prev(JSContext **aContext)
{
    if(!mStack)
        return NS_ERROR_NOT_INITIALIZED;

    *aContext = mStack->ElementAt(mPosition).cx;

    if(mPosition == 0)
        mStack = nsnull;
    else
        --mPosition;
    
    return NS_OK;
}

deps/mozilla/js/src/xpconnect/tests/js/readonlyattributes.js

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/**
 * Verify that we can access but not overwrite the values of read-only 
 * attributes.
 */

 StartTest( "ReadOnly File Attributes" );

 /*
  * These values come from xpctest_attributes.idl and xpctest_attributes.cpp
  */

 var CONTRACTID = "@mozilla.org/js/xpc/test/ObjectReadOnly;1";
 var INAME   = Components.interfaces["nsIXPCTestObjectReadOnly"];

 var o = Components.classes[CONTRACTID].createInstance();
 o = o.QueryInterface( INAME );

 AddTestCase( "o.boolReadOnly", true, o.boolReadOnly );
 AddTestCase( "o.shortReadOnly", 32767, o.shortReadOnly );
 AddTestCase( "o.longReadOnly", 2147483647, o.longReadOnly );
 AddTestCase( "o.charReadOnly", "X", o.charReadOnly );
			  
 // read only means we can't overwrite.

 o.boolReadOnly = false;
 o.shortReadOnly = -12345;
 o.longReadOnly = 12345;
 o.charReadOnly = "Z";

 AddTestCase( "o.boolReadOnly", true, o.boolReadOnly );
 AddTestCase( "o.shortReadOnly", 32767, o.shortReadOnly );
 AddTestCase( "o.longReadOnly", 2147483647, o.longReadOnly );
 AddTestCase( "o.charReadOnly", "X", o.charReadOnly );

 StopTest();

deps/mozilla/js/src/xpconnect/tests/js/readwriteattributes.js

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/**
 * Verify that we can access but not overwrite the values of read-only 
 * attributes.
 */

 StartTest( "Read-Write Attributes" );

 /*
  * These values come from xpctest_attributes.idl and xpctest_attributes.cpp
  */

 var CONTRACTID = "@mozilla.org/js/xpc/test/ObjectReadWrite;1";
 var INAME   = Components.interfaces["nsIXPCTestObjectReadWrite"];

 var O = Components.classes[CONTRACTID].createInstance();
 o = O.QueryInterface( INAME );


 AddTestCase( "typeof Components.classes[" + CONTRACTID+"].createInstance()",
			   "object",
			   typeof O );

 AddTestCase( "typeof O.QueryInterface[" +INAME+"]",
			"object",
			typeof o );

 AddTestCase( "o.booleanProperty", true, o.booleanProperty );
 AddTestCase( "o.shortProperty", 32767, o.shortProperty );
 AddTestCase( "o.longProperty", 2147483647, o.longProperty );
 AddTestCase( "o.charProperty", "X", o.charProperty );
			  
 // these we can overwrite

 o.booleanProperty = false;
 o.shortProperty = -12345;
 o.longProperty = 1234567890;
 o.charProperty = "Z";

 AddTestCase( "o.booleanProperty", false, o.booleanProperty );
 AddTestCase( "o.shortProperty", -12345, o.shortProperty );
 AddTestCase( "o.longProperty", 1234567890, o.longProperty );
 AddTestCase( "o.charProperty", "Z", o.charProperty );

 // try assigning values that differ from the expected type to verify
 // conversion
 SetAndTestBooleanProperty( false, false );
 SetAndTestBooleanProperty( 1, true );
 SetAndTestBooleanProperty( null, false );
 SetAndTestBooleanProperty( "A", true );
 SetAndTestBooleanProperty( undefined, false );
 SetAndTestBooleanProperty( [], true );
 SetAndTestBooleanProperty( {}, true );

 StopTest();

 function SetAndTestBooleanProperty( newValue, expectedValue ) {
	 o.booleanProperty = newValue;

	 AddTestCase( "o.booleanProperty = " + newValue +"; o.booleanProperty", 
				expectedValue, 
				o.booleanProperty );
 }

deps/mozilla/nsprpub/lib/libc/README

NSPR 2.0 libc functions
-----------------------

Last edited: AOF 04 March 1997

This directory contains various libc-types of functions. All functions in
this directory are platform independent, thread friendly (both safe and
efficient). They are contributed from various sources, though the contri-
butions are monitored by the NSPR group (mailto:freier).

All API items exported by these functions will contain the same three
character prefix, "PL_" (Portable Library). Internal function names
that are not exported (static) are of little concern, though some caution
must be used on those elements that are 'extern' but not really intended
to be part of the API. Those should all have a prefix of "_PL_" (is that
legal?).

The responsibility for contributions in this area are distributed among
all interested parties.

deps/mozilla/nsprpub/lib/libc/include/README

NSPR 2.0 libc functions
-----------------------

Last edited: AOF 04 March 1997

This directory contains the API for various libc-types of functions.

deps/mozilla/nsprpub/lib/libc/src/README

NSPR 2.0 libc functions
-----------------------

Last edited: AOF 04 March 1997

This directory contains various libc-types of functions. All functions in
this directory are platform independent, thread friendly (both safe and
efficient). They are contributed from various sources, though the contri-
butions are monitored by the NSPR group (mailto:freier).

All API items exported by these functions will contain the same three
character prefix, "PL_" (Portable Library). Internal function names
that are not exported (static) are of little concern, though some caution
must be used on those elements that are 'extern' but not really intended
to be part of the API. Those should all have a prefix of "_PL_" (is that
legal?).

The responsibility for contributions in this area are distributed among
all interested parties.

deps/mozilla/nsprpub/pr/include/md/_nspr_pthread.h

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef nspr_pthread_defs_h___
#define nspr_pthread_defs_h___

#include <pthread.h>
#include "prthread.h"

#if defined(PTHREADS_USER)
/*
** Thread Local Storage 
*/
extern pthread_key_t current_thread_key;
extern pthread_key_t current_cpu_key;
extern pthread_key_t last_thread_key;
extern pthread_key_t intsoff_key;

#define _MD_CURRENT_THREAD() 			\
			((struct PRThread *) pthread_getspecific(current_thread_key))
#define _MD_CURRENT_CPU() 				\
			((struct _PRCPU *) pthread_getspecific(current_cpu_key))
#define _MD_LAST_THREAD()				\
			((struct PRThread *) pthread_getspecific(last_thread_key))
	
#define _MD_SET_CURRENT_THREAD(newval) 			\
	pthread_setspecific(current_thread_key, (void *)newval)

#define _MD_SET_CURRENT_CPU(newval) 			\
	pthread_setspecific(current_cpu_key, (void *)newval)

#define _MD_SET_LAST_THREAD(newval)	 			\
	pthread_setspecific(last_thread_key, (void *)newval)

#define _MD_SET_INTSOFF(_val)
#define _MD_GET_INTSOFF()	1
	
/*
** Initialize the thread context preparing it to execute _main.
*/
#define _MD_INIT_CONTEXT(_thread, _sp, _main, status)			\
    PR_BEGIN_MACRO				      							\
        *status = PR_TRUE;              						\
		if (SAVE_CONTEXT(_thread)) {							\
	    	(*_main)();											\
		}														\
		_MD_SET_THR_SP(_thread, _sp);							\
		_thread->no_sched = 0; 									\
    PR_END_MACRO

#define _MD_SWITCH_CONTEXT(_thread)  								\
    PR_BEGIN_MACRO 													\
	PR_ASSERT(_thread->no_sched);									\
	if (!SAVE_CONTEXT(_thread)) {									\
		(_thread)->md.errcode = errno;  							\
		_MD_SET_LAST_THREAD(_thread);								\
		_PR_Schedule();		     									\
    } else {														\
		 (_MD_LAST_THREAD())->no_sched = 0;							\
	}																\
    PR_END_MACRO

/*
** Restore a thread context, saved by _MD_SWITCH_CONTEXT
*/
#define _MD_RESTORE_CONTEXT(_thread)								\
    PR_BEGIN_MACRO 													\
    errno = (_thread)->md.errcode; 									\
    _MD_SET_CURRENT_THREAD(_thread); 								\
	_thread->no_sched = 1;											\
    GOTO_CONTEXT(_thread); 											\
    PR_END_MACRO


/* Machine-dependent (MD) data structures */

struct _MDThread {
    jmp_buf 		jb;
    int				id;
    int				errcode;
	pthread_t		pthread;
	pthread_mutex_t	pthread_mutex;
	pthread_cond_t	pthread_cond;
	int				wait;
};

struct _MDThreadStack {
    PRInt8 notused;
};

struct _MDLock {
	pthread_mutex_t mutex;
};

struct _MDSemaphore {
    PRInt8 notused;
};

struct _MDCVar {
	pthread_mutex_t mutex;
};

struct _MDSegment {
    PRInt8 notused;
};

/*
 * md-specific cpu structure field
 */
#define _PR_MD_MAX_OSFD FD_SETSIZE

struct _MDCPU_Unix {
    PRCList ioQ;
    PRUint32 ioq_timeout;
    PRInt32 ioq_max_osfd;
    PRInt32 ioq_osfd_cnt;
#ifndef _PR_USE_POLL
    fd_set fd_read_set, fd_write_set, fd_exception_set;
    PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
				fd_exception_cnt[_PR_MD_MAX_OSFD];
#else
	struct pollfd *ioq_pollfds;
	int ioq_pollfds_size;
#endif	/* _PR_USE_POLL */
};

#define _PR_IOQ(_cpu)			((_cpu)->md.md_unix.ioQ)
#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
#define _PR_FD_READ_SET(_cpu)		((_cpu)->md.md_unix.fd_read_set)
#define _PR_FD_READ_CNT(_cpu)		((_cpu)->md.md_unix.fd_read_cnt)
#define _PR_FD_WRITE_SET(_cpu)		((_cpu)->md.md_unix.fd_write_set)
#define _PR_FD_WRITE_CNT(_cpu)		((_cpu)->md.md_unix.fd_write_cnt)
#define _PR_FD_EXCEPTION_SET(_cpu)	((_cpu)->md.md_unix.fd_exception_set)
#define _PR_FD_EXCEPTION_CNT(_cpu)	((_cpu)->md.md_unix.fd_exception_cnt)
#define _PR_IOQ_TIMEOUT(_cpu)		((_cpu)->md.md_unix.ioq_timeout)
#define _PR_IOQ_MAX_OSFD(_cpu)		((_cpu)->md.md_unix.ioq_max_osfd)
#define _PR_IOQ_OSFD_CNT(_cpu)		((_cpu)->md.md_unix.ioq_osfd_cnt)
#define _PR_IOQ_POLLFDS(_cpu)		((_cpu)->md.md_unix.ioq_pollfds)
#define _PR_IOQ_POLLFDS_SIZE(_cpu)	((_cpu)->md.md_unix.ioq_pollfds_size)

#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)	32

struct _MDCPU {
    jmp_buf 			jb;
	pthread_t 			pthread;
	struct _MDCPU_Unix 	md_unix;
};

/*
#define _MD_NEW_LOCK(lock) PR_SUCCESS
#define _MD_FREE_LOCK(lock)
#define _MD_LOCK(lock)
#define _MD_UNLOCK(lock)
*/

extern pthread_mutex_t _pr_heapLock;

#define _PR_LOCK(lock) pthread_mutex_lock(lock)

#define _PR_UNLOCK(lock) pthread_mutex_unlock(lock)


#define _PR_LOCK_HEAP()	{									\
				if (_pr_primordialCPU) {					\
					_PR_LOCK(_pr_heapLock);					\
				}

#define _PR_UNLOCK_HEAP() 	if (_pr_primordialCPU)	{		\
					_PR_UNLOCK(_pr_heapLock);				\
				}											\
			  }

NSPR_API(PRStatus) _MD_NEW_LOCK(struct _MDLock *md);
NSPR_API(void) _MD_FREE_LOCK(struct _MDLock *lockp);

#define _MD_LOCK(_lockp) _PR_LOCK(&(_lockp)->mutex)
#define _MD_UNLOCK(_lockp) _PR_UNLOCK(&(_lockp)->mutex)

#define _MD_INIT_IO()
#define _MD_IOQ_LOCK()
#define _MD_IOQ_UNLOCK()
#define _MD_CHECK_FOR_EXIT()

NSPR_API(PRStatus) _MD_InitThread(struct PRThread *thread);
#define _MD_INIT_THREAD _MD_InitThread
#define _MD_INIT_ATTACHED_THREAD _MD_InitThread

NSPR_API(void) _MD_ExitThread(struct PRThread *thread);
#define _MD_EXIT_THREAD _MD_ExitThread

NSPR_API(void) _MD_SuspendThread(struct PRThread *thread);
#define _MD_SUSPEND_THREAD _MD_SuspendThread

NSPR_API(void) _MD_ResumeThread(struct PRThread *thread);
#define _MD_RESUME_THREAD _MD_ResumeThread

NSPR_API(void) _MD_SuspendCPU(struct _PRCPU *thread);
#define _MD_SUSPEND_CPU _MD_SuspendCPU

NSPR_API(void) _MD_ResumeCPU(struct _PRCPU *thread);
#define _MD_RESUME_CPU _MD_ResumeCPU

#define _MD_BEGIN_SUSPEND_ALL()
#define _MD_END_SUSPEND_ALL()
#define _MD_BEGIN_RESUME_ALL()
#define _MD_END_RESUME_ALL()

NSPR_API(void) _MD_EarlyInit(void);
#define _MD_EARLY_INIT _MD_EarlyInit

#define _MD_FINAL_INIT _PR_UnixInit

NSPR_API(void) _MD_InitLocks(void);
#define _MD_INIT_LOCKS _MD_InitLocks

NSPR_API(void) _MD_CleanThread(struct PRThread *thread);
#define _MD_CLEAN_THREAD _MD_CleanThread

NSPR_API(PRStatus) _MD_CreateThread(
                        struct PRThread *thread,
                        void (*start) (void *),
                        PRThreadPriority priority,
                        PRThreadScope scope,
                        PRThreadState state,
                        PRUint32 stackSize);
#define _MD_CREATE_THREAD _MD_CreateThread

extern void _MD_CleanupBeforeExit(void);
#define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit

NSPR_API(void) _MD_InitRunningCPU(struct _PRCPU *cpu);
#define    _MD_INIT_RUNNING_CPU _MD_InitRunningCPU

/* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and
 * awaken a thread which is waiting on a lock or cvar.
 */
NSPR_API(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout);
#define _MD_WAIT _MD_wait

NSPR_API(PRStatus) _MD_WakeupWaiter(struct PRThread *);
#define _MD_WAKEUP_WAITER _MD_WakeupWaiter

NSPR_API(void) _MD_SetPriority(struct _MDThread *thread,
	PRThreadPriority newPri);
#define _MD_SET_PRIORITY _MD_SetPriority

#endif /* PTHREADS_USER */

#endif /* nspr_pthread_defs_h___ */

deps/mozilla/nsprpub/pr/include/prthread.h

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef prthread_h___
#define prthread_h___

/*
** API for NSPR threads. On some architectures (Mac OS Classic
** notably) pre-emptibility is not guaranteed. Hard priority scheduling
** is not guaranteed, so programming using priority based synchronization
** is a no-no.
**
** NSPR threads are scheduled based loosely on their client set priority.
** In general, a thread of a higher priority has a statistically better
** chance of running relative to threads of lower priority. However,
** NSPR uses multiple strategies to provide execution vehicles for thread
** abstraction of various host platforms. As it turns out, there is little
** NSPR can do to affect the scheduling attributes of "GLOBAL" threads.
** However, a semblance of GLOBAL threads is used to implement "LOCAL"
** threads. An arbitrary number of such LOCAL threads can be assigned to
** a single GLOBAL thread.
**
** For scheduling, NSPR will attempt to run the highest priority LOCAL
** thread associated with a given GLOBAL thread. It is further assumed
** that the host OS will apply some form of "fair" scheduling on the
** GLOBAL threads.
**
** Threads have a "system flag" which when set indicates the thread
** doesn't count for determining when the process should exit (the
** process exits when the last user thread exits).
**
** Threads also have a "scope flag" which controls whether the threads
** are scheduled in the local scope or scheduled by the OS globally. This 
** indicates whether a thread is permanently bound to a native OS thread. 
** An unbound thread competes for scheduling resources in the same process.
**
** Another flag is "state flag" which control whether the thread is joinable.
** It allows other threads to wait for the created thread to reach completion.
**
** Threads can have "per-thread-data" attached to them. Each thread has a
** per-thread error number and error string which are updated when NSPR
** operations fail.
*/
#include "prtypes.h"
#include "prinrval.h"

PR_BEGIN_EXTERN_C

typedef struct PRThread PRThread;
typedef struct PRThreadStack PRThreadStack;

typedef enum PRThreadType {
    PR_USER_THREAD,
    PR_SYSTEM_THREAD
} PRThreadType;

typedef enum PRThreadScope {
    PR_LOCAL_THREAD,
    PR_GLOBAL_THREAD,
    PR_GLOBAL_BOUND_THREAD
} PRThreadScope;

typedef enum PRThreadState {
    PR_JOINABLE_THREAD,
    PR_UNJOINABLE_THREAD
} PRThreadState;

typedef enum PRThreadPriority
{
    PR_PRIORITY_FIRST = 0,      /* just a placeholder */
    PR_PRIORITY_LOW = 0,        /* the lowest possible priority */
    PR_PRIORITY_NORMAL = 1,     /* most common expected priority */
    PR_PRIORITY_HIGH = 2,       /* slightly more aggressive scheduling */
    PR_PRIORITY_URGENT = 3,     /* it does little good to have more than one */
    PR_PRIORITY_LAST = 3        /* this is just a placeholder */
} PRThreadPriority;

/*
** Create a new thread:
**     "type" is the type of thread to create
**     "start(arg)" will be invoked as the threads "main"
**     "priority" will be created thread's priority
**     "scope" will specify whether the thread is local or global
**     "state" will specify whether the thread is joinable or not
**     "stackSize" the size of the stack, in bytes. The value can be zero
**        and then a machine specific stack size will be chosen.
**
** This can return NULL if some kind of error occurs, such as if memory is
** tight.
**
** If you want the thread to start up waiting for the creator to do
** something, enter a lock before creating the thread and then have the
** threads start routine enter and exit the same lock. When you are ready
** for the thread to run, exit the lock.
**
** If you want to detect the completion of the created thread, the thread
** should be created joinable.  Then, use PR_JoinThread to synchrnoize the
** termination of another thread.
**
** When the start function returns the thread exits. If it is the last
** PR_USER_THREAD to exit then the process exits.
*/
NSPR_API(PRThread*) PR_CreateThread(PRThreadType type,
                     void (PR_CALLBACK *start)(void *arg),
                     void *arg,
                     PRThreadPriority priority,
                     PRThreadScope scope,
                     PRThreadState state,
                     PRUint32 stackSize);

/*
** Wait for thread termination:
**     "thread" is the target thread 
**
** This can return PR_FAILURE if no joinable thread could be found 
** corresponding to the specified target thread.
**
** The calling thread is blocked until the target thread completes.
** Several threads cannot wait for the same thread to complete; one thread
** will operate successfully and others will terminate with an error PR_FAILURE.
** The calling thread will not be blocked if the target thread has already
** terminated.
*/
NSPR_API(PRStatus) PR_JoinThread(PRThread *thread);

/*
** Return the current thread object for the currently running code.
** Never returns NULL.
*/
NSPR_API(PRThread*) PR_GetCurrentThread(void);
#ifndef NO_NSPR_10_SUPPORT
#define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */
#endif /* NO_NSPR_10_SUPPORT */

/*
** Get the priority of "thread".
*/
NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread);

/*
** Change the priority of the "thread" to "priority".
*/
NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority);

/*
** This routine returns a new index for per-thread-private data table. 
** The index is visible to all threads within a process. This index can 
** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines 
** to save and retrieve data associated with the index for a thread.
**
** Each index is associationed with a destructor function ('dtor'). The function
** may be specified as NULL when the index is created. If it is not NULL, the
** function will be called when:
**      - the thread exits and the private data for the associated index
**        is not NULL,
**      - new thread private data is set and the current private data is
**        not NULL.
**
** The index independently maintains specific values for each binding thread. 
** A thread can only get access to its own thread-specific-data.
**
** Upon a new index return the value associated with the index for all threads
** is NULL, and upon thread creation the value associated with all indices for 
** that thread is NULL. 
**
** Returns PR_FAILURE if the total number of indices will exceed the maximun 
** allowed.
*/
typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);

NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
    PRUintn *newIndex, PRThreadPrivateDTOR destructor);

/*
** Define some per-thread-private data.
**     "tpdIndex" is an index into the per-thread private data table
**     "priv" is the per-thread-private data 
**
** If the per-thread private data table has a previously registered
** destructor function and a non-NULL per-thread-private data value,
** the destructor function is invoked.
**
** This can return PR_FAILURE if the index is invalid.
*/
NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv);

/*
** Recover the per-thread-private data for the current thread. "tpdIndex" is
** the index into the per-thread private data table. 
**
** The returned value may be NULL which is indistinguishable from an error 
** condition.
**
** A thread can only get access to its own thread-specific-data.
*/
NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex);

/*
** This routine sets the interrupt request for a target thread. The interrupt
** request remains in the thread's state until it is delivered exactly once
** or explicitly canceled.
**
** A thread that has been interrupted will fail all NSPR blocking operations
** that return a PRStatus (I/O, waiting on a condition, etc).
**
** PR_Interrupt may itself fail if the target thread is invalid.
*/
NSPR_API(PRStatus) PR_Interrupt(PRThread *thread);

/*
** Clear the interrupt request for the calling thread. If no such request
** is pending, this operation is a noop.
*/
NSPR_API(void) PR_ClearInterrupt(void);

/*
** Block the interrupt for the calling thread.
*/
NSPR_API(void) PR_BlockInterrupt(void);

/*
** Unblock the interrupt for the calling thread.
*/
NSPR_API(void) PR_UnblockInterrupt(void);

/*
** Make the current thread sleep until "ticks" time amount of time
** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is
** equivalent to calling PR_Yield. Calling PR_Sleep with an argument
** equivalent to PR_INTERVAL_NO_TIMEOUT is an error and will result
** in a PR_FAILURE error return.
*/
NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks);

/*
** Get the scoping of this thread.
*/
NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread);

/*
** Get the type of this thread.
*/
NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread);

/*
** Get the join state of this thread.
*/
NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread);

PR_END_EXTERN_C

#endif /* prthread_h___ */

deps/mozilla/nsprpub/pr/src/bthreads/


        

deps/mozilla/nsprpub/pr/src/bthreads/.cvsignore

Makefile

deps/mozilla/nsprpub/pr/src/bthreads/Makefile.in

# 
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Portable Runtime (NSPR).
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****


#! gmake

MOD_DEPTH	= ../../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(MOD_DEPTH)/config/autoconf.mk

include $(topsrcdir)/config/config.mk

include $(srcdir)/bsrcs.mk
CSRCS += $(BTCSRCS)

TARGETS	= $(OBJS)

INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private

include $(topsrcdir)/config/rules.mk

DEFINES		+= -D_NSPR_BUILD_

export:: $(TARGETS)


deps/mozilla/nsprpub/pr/src/bthreads/bsrcs.mk

# 
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Portable Runtime (NSPR).
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****

# this file lists the source files to be compiled (used in Makefile) and
# then enumerated as object files (in objs.mk) for inclusion in the NSPR
# shared library

BTCSRCS = \
	btthread.c \
	btlocks.c \
	btcvar.c \
	btmon.c \
	btsem.c \
	btmisc.c \
	$(NULL)

deps/mozilla/nsprpub/pr/src/bthreads/btcvar.c

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <kernel/OS.h>

#include "primpl.h"

/*
** Create a new condition variable.
**
** 	"lock" is the lock used to protect the condition variable.
**
** Condition variables are synchronization objects that threads can use
** to wait for some condition to occur.
**
** This may fail if memory is tight or if some operating system resource
** is low. In such cases, a NULL will be returned.
*/
PR_IMPLEMENT(PRCondVar*)
    PR_NewCondVar (PRLock *lock)
{
    PRCondVar *cv = PR_NEW( PRCondVar );
    PR_ASSERT( NULL != lock );
    if( NULL != cv )
    {
	cv->lock = lock;
	cv->sem = create_sem(0, "CVSem");
	cv->handshakeSem = create_sem(0, "CVHandshake");
	cv->signalSem = create_sem( 0, "CVSignal");
	cv->signalBenCount = 0;
	cv->ns = cv->nw = 0;
	PR_ASSERT( cv->sem >= B_NO_ERROR );
	PR_ASSERT( cv->handshakeSem >= B_NO_ERROR );
	PR_ASSERT( cv->signalSem >= B_NO_ERROR );
    }
    return cv;
} /* PR_NewCondVar */

/*
** Destroy a condition variable. There must be no thread
** waiting on the condvar. The caller is responsible for guaranteeing
** that the condvar is no longer in use.
**
*/
PR_IMPLEMENT(void)
    PR_DestroyCondVar (PRCondVar *cvar)
{
    status_t result = delete_sem( cvar->sem );
    PR_ASSERT( result == B_NO_ERROR );
    
    result = delete_sem( cvar->handshakeSem );
    PR_ASSERT( result == B_NO_ERROR );

    result = delete_sem( cvar->signalSem );
    PR_ASSERT( result == B_NO_ERROR );

    PR_DELETE( cvar );
}

/*
** The thread that waits on a condition is blocked in a "waiting on
** condition" state until another thread notifies the condition or a
** caller specified amount of time expires. The lock associated with
** the condition variable will be released, which must have be held
** prior to the call to wait.
**
** Logically a notified thread is moved from the "waiting on condition"
** state and made "ready." When scheduled, it will attempt to reacquire
** the lock that it held when wait was called.
**
** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and
** PR_INTERVAL_NO_WAIT. The former value requires that a condition be
** notified (or the thread interrupted) before it will resume from the
** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect
** is to release the lock, possibly causing a rescheduling within the
** runtime, then immediately attempting to reacquire the lock and resume.
**
** Any other value for timeout will cause the thread to be rescheduled
** either due to explicit notification or an expired interval. The latter
** must be determined by treating time as one part of the monitored data
** being protected by the lock and tested explicitly for an expired
** interval.
**
** Returns PR_FAILURE if the caller has not locked the lock associated
** with the condition variable or the thread was interrupted (PR_Interrupt()).
** The particular reason can be extracted with PR_GetError().
*/
PR_IMPLEMENT(PRStatus)
    PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout)
{
    status_t err;
    if( timeout == PR_INTERVAL_NO_WAIT ) 
    {
        PR_Unlock( cvar->lock );
        PR_Lock( cvar->lock );
        return PR_SUCCESS;
    }

    if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) 
    {
        if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) 
        {
            atomic_add( &cvar->signalBenCount, -1 );
            return PR_FAILURE;
        }
    }
    cvar->nw += 1;
    if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) 
    {
        release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE);
    }

    PR_Unlock( cvar->lock );
    if( timeout==PR_INTERVAL_NO_TIMEOUT ) 
    {
    	err = acquire_sem(cvar->sem);
    } 
    else 
    {
    	err = acquire_sem_etc(cvar->sem, 1, B_RELATIVE_TIMEOUT, PR_IntervalToMicroseconds(timeout) );
    }

    if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) 
    {
        while (acquire_sem(cvar->signalSem) == B_INTERRUPTED);
    }

    if (cvar->ns > 0)
    {
        release_sem_etc(cvar->handshakeSem, 1, B_DO_NOT_RESCHEDULE);
        cvar->ns -= 1;
    }
    cvar->nw -= 1;
    if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) 
    {
        release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE);
    }

    PR_Lock( cvar->lock );
    if(err!=B_NO_ERROR) 
    {
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}

/*
** Notify ONE thread that is currently waiting on 'cvar'. Which thread is
** dependent on the implementation of the runtime. Common sense would dictate
** that all threads waiting on a single condition have identical semantics,
** therefore which one gets notified is not significant. 
**
** The calling thead must hold the lock that protects the condition, as
** well as the invariants that are tightly bound to the condition, when
** notify is called.
**
** Returns PR_FAILURE if the caller has not locked the lock associated
** with the condition variable.
*/
PR_IMPLEMENT(PRStatus)
    PR_NotifyCondVar (PRCondVar *cvar)
{
    status_t err ;
    if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) 
    {
        if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) 
        {
            atomic_add( &cvar->signalBenCount, -1 );
            return PR_FAILURE;
        }
    }
    if (cvar->nw > cvar->ns)
    {
        cvar->ns += 1;
        release_sem_etc(cvar->sem, 1, B_DO_NOT_RESCHEDULE);
        if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) 
        {
            release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE);
        }

        while (acquire_sem(cvar->handshakeSem) == B_INTERRUPTED) 
        {
            err = B_INTERRUPTED; 
        }
    }
    else
    {
        if( atomic_add( &cvar->signalBenCount, -1 ) > 1 )
        {
            release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE);
        }
    }
    return PR_SUCCESS; 
}

/*
** Notify all of the threads waiting on the condition variable. The order
** that the threads are notified is indeterminant. The lock that protects
** the condition must be held.
**
** Returns PR_FAILURE if the caller has not locked the lock associated
** with the condition variable.
*/
PR_IMPLEMENT(PRStatus)
    PR_NotifyAllCondVar (PRCondVar *cvar)
{
    int32 handshakes;
    status_t err = B_OK;

    if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) 
    {
        if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) 
        {
            atomic_add( &cvar->signalBenCount, -1 );
            return PR_FAILURE;
        }
    }

    if (cvar->nw > cvar->ns)
    {
        handshakes = cvar->nw - cvar->ns;
        cvar->ns = cvar->nw;				
        release_sem_etc(cvar->sem, handshakes, B_DO_NOT_RESCHEDULE);	
        if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) 
        {
            release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE);
        }

        while (acquire_sem_etc(cvar->handshakeSem, handshakes, 0, 0) == B_INTERRUPTED) 
        {
            err = B_INTERRUPTED; 
        }
    }
    else
    {
        if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) 
        {
            release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE);
        }
    }
    return PR_SUCCESS;
}

deps/mozilla/nsprpub/pr/src/bthreads/btlocks.c

/* -*- Mode: C++; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
** File:        btlocks.c
** Description: Implemenation for thread locks using bthreads
** Exports:     prlock.h
*/

#include "primpl.h"

#include <string.h>
#include <sys/time.h>

void
_PR_InitLocks (void)
{
}

PR_IMPLEMENT(PRLock*)
    PR_NewLock (void)
{
    PRLock *lock;
    status_t semresult;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    lock = PR_NEWZAP(PRLock);
    if (lock != NULL) {

	lock->benaphoreCount = 0;
	lock->semaphoreID = create_sem( 0, "nsprLockSem" );
	if( lock->semaphoreID < B_NO_ERROR ) {

	    PR_DELETE( lock );
	    lock = NULL;
	}
    }

    return lock;
}

PR_IMPLEMENT(void)
    PR_DestroyLock (PRLock* lock)
{
    status_t result;

    PR_ASSERT(NULL != lock);
    result = delete_sem(lock->semaphoreID);
    PR_ASSERT(result == B_NO_ERROR);
    PR_DELETE(lock);
}

PR_IMPLEMENT(void)
    PR_Lock (PRLock* lock)
{
    PR_ASSERT(lock != NULL);

    if( atomic_add( &lock->benaphoreCount, 1 ) > 0 ) {

	if( acquire_sem(lock->semaphoreID ) != B_NO_ERROR ) {

	    atomic_add( &lock->benaphoreCount, -1 );
	    return;
	}
    }

    lock->owner = find_thread( NULL );
}

PR_IMPLEMENT(PRStatus)
    PR_Unlock (PRLock* lock)
{
    PR_ASSERT(lock != NULL);
    lock->owner = NULL;
    if( atomic_add( &lock->benaphoreCount, -1 ) > 1 ) {

	release_sem_etc( lock->semaphoreID, 1, B_DO_NOT_RESCHEDULE );
    }

    return PR_SUCCESS;
}

PR_IMPLEMENT(void)
    PR_AssertCurrentThreadOwnsLock(PRLock *lock)
{
    PR_ASSERT(lock != NULL);
    PR_ASSERT(lock->owner == find_thread( NULL ));
}

deps/mozilla/nsprpub/pr/src/bthreads/btmisc.c

/* -*- Mode: C++; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"
#include <stdio.h>

// void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")}
// void _MD_StartInterrupts(void) {PT_LOG("_MD_StartInterrupts")}

/* this is a total hack.. */

struct protoent* getprotobyname(const char* name)
{
    return 0;
}

struct protoent* getprotobynumber(int number)
{
    return 0;
}

/* this is needed by prinit for some reason */
void
_PR_InitStacks (void)
{
}

/* this is needed by prinit for some reason */
void
_PR_InitTPD (void)
{
}

/*
** Create extra virtual processor threads. Generally used with MP systems.
*/
PR_IMPLEMENT(void)
    PR_SetConcurrency (PRUintn numCPUs)
{
}

/*
** Set thread recycle mode to on (1) or off (0)
*/
PR_IMPLEMENT(void)
    PR_SetThreadRecycleMode (PRUint32 flag)
{
}

/*
** Get context registers, return with error for now.
*/

PR_IMPLEMENT(PRWord *)
_MD_HomeGCRegisters( PRThread *t, int isCurrent, int *np )
{
     return 0;
}

PR_IMPLEMENT(void *)
PR_GetSP( PRThread *t )
{
    return 0;
}

PR_IMPLEMENT(PRStatus)
PR_EnumerateThreads( PREnumerator func, void *arg )
{
    return PR_FAILURE;
}

deps/mozilla/nsprpub/pr/src/bthreads/btmon.c

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <kernel/OS.h>

#include "primpl.h"

/*
** Create a new monitor. Monitors are re-entrant locks with a single built-in
** condition variable.
**
** This may fail if memory is tight or if some operating system resource
** is low.
*/
PR_IMPLEMENT(PRMonitor*)
    PR_NewMonitor (void)
{
    PRMonitor *mon;
    PRCondVar *cvar;
    PRLock    *lock;

    mon = PR_NEWZAP( PRMonitor );
    if( mon )
    {
	lock = PR_NewLock();
	if( !lock )
        {
	    PR_DELETE( mon );
	    return( 0 );
	}

	cvar = PR_NewCondVar( lock );
	if( !cvar )
	{
	    PR_DestroyLock( lock );
	    PR_DELETE( mon );
	    return( 0 );
	}

	mon->cvar = cvar;
	mon->name = NULL;
    }

    return( mon );
}

PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
{
    PRMonitor* mon = PR_NewMonitor();
    if( mon )
    {
        mon->name = name;
    }
    return mon;
}

/*
** Destroy a monitor. The caller is responsible for guaranteeing that the
** monitor is no longer in use. There must be no thread waiting on the
** monitor's condition variable and that the lock is not held.
**
*/
PR_IMPLEMENT(void)
    PR_DestroyMonitor (PRMonitor *mon)
{
    PR_DestroyLock( mon->cvar->lock );
    PR_DestroyCondVar( mon->cvar );
    PR_DELETE( mon );
}

/*
** Enter the lock associated with the monitor. If the calling thread currently
** is in the monitor, the call to enter will silently succeed. In either case,
** it will increment the entry count by one.
*/
PR_IMPLEMENT(void)
    PR_EnterMonitor (PRMonitor *mon)
{
    if( mon->cvar->lock->owner == find_thread( NULL ) )
    {
	mon->entryCount++;

    } else
    {
	PR_Lock( mon->cvar->lock );
	mon->entryCount = 1;
    }
}

/*
** Decrement the entry count associated with the monitor. If the decremented
** entry count is zero, the monitor is exited. Returns PR_FAILURE if the
** calling thread has not entered the monitor.
*/
PR_IMPLEMENT(PRStatus)
    PR_ExitMonitor (PRMonitor *mon)
{
    if( mon->cvar->lock->owner != find_thread( NULL ) )
    {
	return( PR_FAILURE );
    }
    if( --mon->entryCount == 0 )
    {
	return( PR_Unlock( mon->cvar->lock ) );
    }
    return( PR_SUCCESS );
}

/*
** Wait for a notify on the monitor's condition variable. Sleep for "ticks"
** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is
** indefinite).
**
** While the thread is waiting it exits the monitor (as if it called
** PR_ExitMonitor as many times as it had called PR_EnterMonitor).  When
** the wait has finished the thread regains control of the monitors lock
** with the same entry count as before the wait began.
**
** The thread waiting on the monitor will be resumed when the monitor is
** notified (assuming the thread is the next in line to receive the
** notify) or when the "ticks" timeout elapses.
**
** Returns PR_FAILURE if the caller has not entered the monitor.
*/
PR_IMPLEMENT(PRStatus)
    PR_Wait (PRMonitor *mon, PRIntervalTime ticks)
{
    PRUint32 entryCount;
    PRUintn  status;
    PRThread *meThread;
    thread_id me = find_thread( NULL );
    meThread = PR_GetCurrentThread();

    if( mon->cvar->lock->owner != me ) return( PR_FAILURE );

    entryCount = mon->entryCount;
    mon->entryCount = 0;

    status = PR_WaitCondVar( mon->cvar, ticks );

    mon->entryCount = entryCount;

    return( status );
}

/*
** Notify a thread waiting on the monitor's condition variable. If a thread
** is waiting on the condition variable (using PR_Wait) then it is awakened
** and attempts to reenter the monitor.
*/
PR_IMPLEMENT(PRStatus)
    PR_Notify (PRMonitor *mon)
{
    if( mon->cvar->lock->owner != find_thread( NULL ) )
    {
	return( PR_FAILURE );
    }

    PR_NotifyCondVar( mon->cvar );
    return( PR_SUCCESS );
}

/*
** Notify all of the threads waiting on the monitor's condition variable.
** All of threads waiting on the condition are scheduled to reenter the
** monitor.
*/
PR_IMPLEMENT(PRStatus)
    PR_NotifyAll (PRMonitor *mon)
{
    if( mon->cvar->lock->owner != find_thread( NULL ) )
    {
	return( PR_FAILURE );
    }

    PR_NotifyAllCondVar( mon->cvar );
    return( PR_SUCCESS );
}

/*
** Return the number of times that the current thread has entered the
** lock. Returns zero if the current thread has not entered the lock.
*/
PR_IMPLEMENT(PRIntn)
    PR_GetMonitorEntryCount(PRMonitor *mon)
{
    return( (mon->cvar->lock->owner == find_thread( NULL )) ?
            mon->entryCount : 0 );
}

/*
** If the current thread is in |mon|, this assertion is guaranteed to
** succeed.  Otherwise, the behavior of this function is undefined.
*/
PR_IMPLEMENT(void)
    PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
{
    PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(mon->cvar->lock);
}

deps/mozilla/nsprpub/pr/src/bthreads/btsem.c

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <kernel/OS.h>

#include "primpl.h"

/*
** Create a new semaphore object.
*/
PR_IMPLEMENT(PRSemaphore*)
    PR_NewSem (PRUintn value)
{
	PRSemaphore *semaphore;

	if (!_pr_initialized) _PR_ImplicitInitialization();

	semaphore = PR_NEWZAP(PRSemaphore);
	if (NULL != semaphore) {
		if ((semaphore->sem = create_sem(value, "nspr_sem")) < B_NO_ERROR)
			return NULL;
		else 
			return semaphore;
	}
	return NULL;
}

/*
** Destroy the given semaphore object.
**
*/
PR_IMPLEMENT(void)
    PR_DestroySem (PRSemaphore *sem)
{
	status_t result;

	PR_ASSERT(sem != NULL);
	result = delete_sem(sem->sem);
	PR_ASSERT(result == B_NO_ERROR);
	PR_DELETE(sem);
} 

/*
** Wait on a Semaphore.
** 
** This routine allows a calling thread to wait or proceed depending upon
** the state of the semahore sem. The thread can proceed only if the
** counter value of the semaphore sem is currently greater than 0. If the
** value of semaphore sem is positive, it is decremented by one and the
** routine returns immediately allowing the calling thread to continue. If
** the value of semaphore sem is 0, the calling thread blocks awaiting the
** semaphore to be released by another thread.
** 
** This routine can return PR_PENDING_INTERRUPT if the waiting thread 
** has been interrupted.
*/
PR_IMPLEMENT(PRStatus)
    PR_WaitSem (PRSemaphore *sem)
{
	PR_ASSERT(sem != NULL);
	if (acquire_sem(sem->sem) == B_NO_ERROR)
		return PR_SUCCESS;
	else
		return PR_FAILURE;
}

/*
** This routine increments the counter value of the semaphore. If other
** threads are blocked for the semaphore, then the scheduler will
** determine which ONE thread will be unblocked.
*/
PR_IMPLEMENT(void)
    PR_PostSem (PRSemaphore *sem)
{
	status_t result;

	PR_ASSERT(sem != NULL);
	result = release_sem_etc(sem->sem, 1, B_DO_NOT_RESCHEDULE);
	PR_ASSERT(result == B_NO_ERROR);
}

/*
** Returns the value of the semaphore referenced by sem without affecting
** the state of the semaphore.  The value represents the semaphore value
** at the time of the call, but may not be the actual value when the
** caller inspects it.
*/
PR_IMPLEMENT(PRUintn)
    PR_GetValueSem (PRSemaphore *sem)
{
	sem_info	info;

	PR_ASSERT(sem != NULL);
	get_sem_info(sem->sem, &info);
	return info.count;
}

deps/mozilla/nsprpub/pr/src/bthreads/btthread.c

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <kernel/OS.h>
#include <support/TLS.h>

#include "prlog.h"
#include "primpl.h"
#include "prcvar.h"
#include "prpdce.h"

#include <stdlib.h>
#include <string.h>
#include <signal.h>

/* values for PRThread.state */
#define BT_THREAD_PRIMORD   0x01    /* this is the primordial thread */
#define BT_THREAD_SYSTEM    0x02    /* this is a system thread */
#define BT_THREAD_JOINABLE  0x04	/* this is a joinable thread */

struct _BT_Bookeeping
{
    PRLock *ml;                 /* a lock to protect ourselves */
	sem_id cleanUpSem;		/* the primoridal thread will block on this
							   sem while waiting for the user threads */
    PRInt32 threadCount;	/* user thred count */

} bt_book = { NULL, B_ERROR, 0 };


#define BT_TPD_LIMIT 128	/* number of TPD slots we'll provide (arbitrary) */

/* these will be used to map an index returned by PR_NewThreadPrivateIndex()
   to the corresponding beos native TLS slot number, and to the destructor
   for that slot - note that, because it is allocated globally, this data
   will be automatically zeroed for us when the program begins */
static int32 tpd_beosTLSSlots[BT_TPD_LIMIT];
static PRThreadPrivateDTOR tpd_dtors[BT_TPD_LIMIT];

static vint32 tpd_slotsUsed=0;	/* number of currently-allocated TPD slots */
static int32 tls_prThreadSlot;	/* TLS slot in which PRThread will be stored */

/* this mutex will be used to synchronize access to every
   PRThread.md.joinSem and PRThread.md.is_joining (we could
   actually allocate one per thread, but that seems a bit excessive,
   especially considering that there will probably be little
   contention, PR_JoinThread() is allowed to block anyway, and the code
   protected by the mutex is short/fast) */
static PRLock *joinSemLock;

static PRUint32 _bt_MapNSPRToNativePriority( PRThreadPriority priority );
static PRThreadPriority _bt_MapNativeToNSPRPriority( PRUint32 priority );
static void _bt_CleanupThread(void *arg);
static PRThread *_bt_AttachThread();

void
_PR_InitThreads (PRThreadType type, PRThreadPriority priority,
                 PRUintn maxPTDs)
{
    PRThread *primordialThread;
    PRUint32  beThreadPriority;

	/* allocate joinSem mutex */
	joinSemLock = PR_NewLock();
	if (joinSemLock == NULL)
	{
		PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
		return;
    }

    /*
    ** Create and initialize NSPR structure for our primordial thread.
    */
    
    primordialThread = PR_NEWZAP(PRThread);
    if( NULL == primordialThread )
    {
        PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
        return;
    }

	primordialThread->md.joinSem = B_ERROR;

    /*
    ** Set the priority to the desired level.
    */

    beThreadPriority = _bt_MapNSPRToNativePriority( priority );
    
    set_thread_priority( find_thread( NULL ), beThreadPriority );
    
    primordialThread->priority = priority;


	/* set the thread's state - note that the thread is not joinable */
    primordialThread->state |= BT_THREAD_PRIMORD;
	if (type == PR_SYSTEM_THREAD)
		primordialThread->state |= BT_THREAD_SYSTEM;

    /*
    ** Allocate a TLS slot for the PRThread structure (just using
    ** native TLS, as opposed to NSPR TPD, will make PR_GetCurrentThread()
    ** somewhat faster, and will leave one more TPD slot for our client)
    */
	
	tls_prThreadSlot = tls_allocate();

    /*
    ** Stuff our new PRThread structure into our thread specific
    ** slot.
    */

	tls_set(tls_prThreadSlot, primordialThread);
    
	/* allocate lock for bt_book */
    bt_book.ml = PR_NewLock();
    if( NULL == bt_book.ml )
    {
    	PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
	return;
    }
}

PRUint32
_bt_MapNSPRToNativePriority( PRThreadPriority priority )
    {
    switch( priority )
    {
    	case PR_PRIORITY_LOW:	 return( B_LOW_PRIORITY );
	case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );
	case PR_PRIORITY_HIGH:	 return( B_DISPLAY_PRIORITY );
	case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );
	default:		 return( B_NORMAL_PRIORITY );
    }
}

PRThreadPriority
_bt_MapNativeToNSPRPriority(PRUint32 priority)
    {
	if (priority < B_NORMAL_PRIORITY)
		return PR_PRIORITY_LOW;
	if (priority < B_DISPLAY_PRIORITY)
		return PR_PRIORITY_NORMAL;
	if (priority < B_URGENT_DISPLAY_PRIORITY)
		return PR_PRIORITY_HIGH;
	return PR_PRIORITY_URGENT;
}

PRUint32
_bt_mapNativeToNSPRPriority( int32 priority )
{
    switch( priority )
    {
    	case PR_PRIORITY_LOW:	 return( B_LOW_PRIORITY );
	case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );
	case PR_PRIORITY_HIGH:	 return( B_DISPLAY_PRIORITY );
	case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );
	default:		 return( B_NORMAL_PRIORITY );
    }
}

/* This method is called by all NSPR threads as they exit */
void _bt_CleanupThread(void *arg)
{
	PRThread *me = PR_GetCurrentThread();
	int32 i;

	/* first, clean up all thread-private data */
	for (i = 0; i < tpd_slotsUsed; i++)
	{
		void *oldValue = tls_get(tpd_beosTLSSlots[i]);
		if ( oldValue != NULL && tpd_dtors[i] != NULL )
			(*tpd_dtors[i])(oldValue);
	}

	/* if this thread is joinable, wait for someone to join it */
	if (me->state & BT_THREAD_JOINABLE)
	{
		/* protect access to our joinSem */
		PR_Lock(joinSemLock);

		if (me->md.is_joining)
		{
			/* someone is already waiting to join us (they've
			   allocated a joinSem for us) - let them know we're
			   ready */
			delete_sem(me->md.joinSem);

			PR_Unlock(joinSemLock);

		}
		else
    {
			/* noone is currently waiting for our demise - it
			   is our responsibility to allocate the joinSem
			   and block on it */
			me->md.joinSem = create_sem(0, "join sem");

			/* we're done accessing our joinSem */
			PR_Unlock(joinSemLock);

			/* wait for someone to join us */
			while (acquire_sem(me->md.joinSem) == B_INTERRUPTED);
	    }
	}

	/* if this is a user thread, we must update our books */
	if ((me->state & BT_THREAD_SYSTEM) == 0)
	{
		/* synchronize access to bt_book */
    PR_Lock( bt_book.ml );

		/* decrement the number of currently-alive user threads */
	bt_book.threadCount--;

		if (bt_book.threadCount == 0 && bt_book.cleanUpSem != B_ERROR) {
			/* we are the last user thread, and the primordial thread is
			   blocked in PR_Cleanup() waiting for us to finish - notify
			   it */
			delete_sem(bt_book.cleanUpSem);
	}

    PR_Unlock( bt_book.ml );
	}

	/* finally, delete this thread's PRThread */
	PR_DELETE(me);
}

/**
 * This is a wrapper that all threads invoke that allows us to set some
 * things up prior to a thread's invocation and clean up after a thread has
 * exited.
 */
static void*
_bt_root (void* arg)
	{
    PRThread *thred = (PRThread*)arg;
    PRIntn rv;
    void *privData;
    status_t result;
    int i;

	/* save our PRThread object into our TLS */
	tls_set(tls_prThreadSlot, thred);

    thred->startFunc(thred->arg);  /* run the dang thing */

	/* clean up */
	_bt_CleanupThread(NULL);

	return 0;
}

PR_IMPLEMENT(PRThread*)
    PR_CreateThread (PRThreadType type, void (*start)(void* arg), void* arg,
                     PRThreadPriority priority, PRThreadScope scope,
                     PRThreadState state, PRUint32 stackSize)
{
    PRUint32 bePriority;

    PRThread* thred;

    if (!_pr_initialized) _PR_ImplicitInitialization();

	thred = PR_NEWZAP(PRThread);
 	if (thred == NULL)
	{
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }

    thred->md.joinSem = B_ERROR;

        thred->arg = arg;
        thred->startFunc = start;
        thred->priority = priority;

	if( state == PR_JOINABLE_THREAD )
	{
	    thred->state |= BT_THREAD_JOINABLE;
	}

        /* keep some books */

	PR_Lock( bt_book.ml );

	if (type == PR_USER_THREAD)
	{
	    bt_book.threadCount++;
        }

	PR_Unlock( bt_book.ml );

	bePriority = _bt_MapNSPRToNativePriority( priority );

        thred->md.tid = spawn_thread((thread_func)_bt_root, "moz-thread",
                                     bePriority, thred);
        if (thred->md.tid < B_OK) {
            PR_SetError(PR_UNKNOWN_ERROR, thred->md.tid);
            PR_DELETE(thred);
			return NULL;
        }

        if (resume_thread(thred->md.tid) < B_OK) {
            PR_SetError(PR_UNKNOWN_ERROR, 0);
            PR_DELETE(thred);
			return NULL;
        }

    return thred;
    }

PR_IMPLEMENT(PRThread*)
	PR_AttachThread(PRThreadType type, PRThreadPriority priority,
					PRThreadStack *stack)
{
	/* PR_GetCurrentThread() will attach a thread if necessary */
	return PR_GetCurrentThread();
}

PR_IMPLEMENT(void)
	PR_DetachThread()
{
	/* we don't support detaching */
}

PR_IMPLEMENT(PRStatus)
    PR_JoinThread (PRThread* thred)
{
    status_t eval, status;

    PR_ASSERT(thred != NULL);

	if ((thred->state & BT_THREAD_JOINABLE) == 0)
    {
	PR_SetError( PR_INVALID_ARGUMENT_ERROR, 0 );
	return( PR_FAILURE );
    }

	/* synchronize access to the thread's joinSem */
	PR_Lock(joinSemLock);
	
	if (thred->md.is_joining)
	{
		/* another thread is already waiting to join the specified
		   thread - we must fail */
		PR_Unlock(joinSemLock);
		return PR_FAILURE;
	}

	/* let others know we are waiting to join */
	thred->md.is_joining = PR_TRUE;

	if (thred->md.joinSem == B_ERROR)
	{
		/* the thread hasn't finished yet - it is our responsibility to
		   allocate a joinSem and wait on it */
		thred->md.joinSem = create_sem(0, "join sem");

		/* we're done changing the joinSem now */
		PR_Unlock(joinSemLock);

		/* wait for the thread to finish */
		while (acquire_sem(thred->md.joinSem) == B_INTERRUPTED);

	}
	else
	{
		/* the thread has already finished, and has allocated the
		   joinSem itself - let it know it can finally die */
		delete_sem(thred->md.joinSem);
		
		PR_Unlock(joinSemLock);
    }

	/* make sure the thread is dead */
    wait_for_thread(thred->md.tid, &eval);

    return PR_SUCCESS;
}

PR_IMPLEMENT(PRThread*)
    PR_GetCurrentThread ()
{
    PRThread* thred;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    thred = (PRThread *)tls_get( tls_prThreadSlot);
	if (thred == NULL)
	{
		/* this thread doesn't have a PRThread structure (it must be
		   a native thread not created by the NSPR) - assimilate it */
		thred = _bt_AttachThread();
	}
    PR_ASSERT(NULL != thred);

    return thred;
}

PR_IMPLEMENT(PRThreadScope)
    PR_GetThreadScope (const PRThread* thred)
{
    PR_ASSERT(thred != NULL);
    return PR_GLOBAL_THREAD;
}

PR_IMPLEMENT(PRThreadType)
    PR_GetThreadType (const PRThread* thred)
{
    PR_ASSERT(thred != NULL);
    return (thred->state & BT_THREAD_SYSTEM) ?
        PR_SYSTEM_THREAD : PR_USER_THREAD;
}

PR_IMPLEMENT(PRThreadState)
    PR_GetThreadState (const PRThread* thred)
{
    PR_ASSERT(thred != NULL);
    return (thred->state & BT_THREAD_JOINABLE)?
    					PR_JOINABLE_THREAD: PR_UNJOINABLE_THREAD;
}

PR_IMPLEMENT(PRThreadPriority)
    PR_GetThreadPriority (const PRThread* thred)
{
    PR_ASSERT(thred != NULL);
    return thred->priority;
}  /* PR_GetThreadPriority */

PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred,
                                        PRThreadPriority newPri)
{
    PRUint32 bePriority;

    PR_ASSERT( thred != NULL );

    thred->priority = newPri;
    bePriority = _bt_MapNSPRToNativePriority( newPri );
    set_thread_priority( thred->md.tid, bePriority );
}

PR_IMPLEMENT(PRStatus)
    PR_NewThreadPrivateIndex (PRUintn* newIndex,
                              PRThreadPrivateDTOR destructor)
{
	int32    index;

    if (!_pr_initialized) _PR_ImplicitInitialization();

	/* reserve the next available tpd slot */
	index = atomic_add( &tpd_slotsUsed, 1 );
	if (index >= BT_TPD_LIMIT)
	{
		/* no slots left - decrement value, then fail */
		atomic_add( &tpd_slotsUsed, -1 );
		PR_SetError( PR_TPD_RANGE_ERROR, 0 );
	    return( PR_FAILURE );
	}

	/* allocate a beos-native TLS slot for this index (the new slot
	   automatically contains NULL) */
	tpd_beosTLSSlots[index] = tls_allocate();

	/* remember the destructor */
	tpd_dtors[index] = destructor;

    *newIndex = (PRUintn)index;

    return( PR_SUCCESS );
}

PR_IMPLEMENT(PRStatus)
    PR_SetThreadPrivate (PRUintn index, void* priv)
{
	void *oldValue;

    /*
    ** Sanity checking
    */

    if(index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT)
    {
		PR_SetError( PR_TPD_RANGE_ERROR, 0 );
	return( PR_FAILURE );
    }

	/* if the old value isn't NULL, and the dtor for this slot isn't
	   NULL, we must destroy the data */
	oldValue = tls_get(tpd_beosTLSSlots[index]);
	if (oldValue != NULL && tpd_dtors[index] != NULL)
		(*tpd_dtors[index])(oldValue);

	/* save new value */
	tls_set(tpd_beosTLSSlots[index], priv);

	    return( PR_SUCCESS );
	}

PR_IMPLEMENT(void*)
    PR_GetThreadPrivate (PRUintn index)
{
	/* make sure the index is valid */
	if (index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT)
    {   
		PR_SetError( PR_TPD_RANGE_ERROR, 0 );
		return NULL;
    }

	/* return the value */
	return tls_get( tpd_beosTLSSlots[index] );
	}


PR_IMPLEMENT(PRStatus)
    PR_Interrupt (PRThread* thred)
{
    PRIntn rv;

    PR_ASSERT(thred != NULL);

    /*
    ** there seems to be a bug in beos R5 in which calling
    ** resume_thread() on a blocked thread returns B_OK instead
    ** of B_BAD_THREAD_STATE (beos bug #20000422-19095).  as such,
    ** to interrupt a thread, we will simply suspend then resume it
    ** (no longer call resume_thread(), check for B_BAD_THREAD_STATE,
    ** the suspend/resume to wake up a blocked thread).  this wakes
    ** up blocked threads properly, and doesn't hurt unblocked threads
    ** (they simply get stopped then re-started immediately)
    */

    rv = suspend_thread( thred->md.tid );
    if( rv != B_NO_ERROR )
    {
        /* this doesn't appear to be a valid thread_id */
        PR_SetError( PR_UNKNOWN_ERROR, rv );
        return PR_FAILURE;
    }

    rv = resume_thread( thred->md.tid );
    if( rv != B_NO_ERROR )
    {
        PR_SetError( PR_UNKNOWN_ERROR, rv );
        return PR_FAILURE;
    }

    return PR_SUCCESS;
}

PR_IMPLEMENT(void)
    PR_ClearInterrupt ()
{
}

PR_IMPLEMENT(PRStatus)
    PR_Yield ()
{
    /* we just sleep for long enough to cause a reschedule (100
       microseconds) */
    snooze(100);
}

#define BT_MILLION 1000000UL

PR_IMPLEMENT(PRStatus)
    PR_Sleep (PRIntervalTime ticks)
{
    bigtime_t tps;
    status_t status;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    tps = PR_IntervalToMicroseconds( ticks );

    status = snooze(tps);
    if (status == B_NO_ERROR) return PR_SUCCESS;

    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, status);
    return PR_FAILURE;
}

PR_IMPLEMENT(PRStatus)
    PR_Cleanup ()
{
    PRThread *me = PR_GetCurrentThread();

    PR_ASSERT(me->state & BT_THREAD_PRIMORD);
    if ((me->state & BT_THREAD_PRIMORD) == 0) {
        return PR_FAILURE;
    }

    PR_Lock( bt_book.ml );

	if (bt_book.threadCount != 0)
    {
		/* we'll have to wait for some threads to finish - create a
		   sem to block on */
		bt_book.cleanUpSem = create_sem(0, "cleanup sem");
    }

    PR_Unlock( bt_book.ml );

	/* note that, if all the user threads were already dead, we
	   wouldn't have created a sem above, so this acquire_sem()
	   will fail immediately */
	while (acquire_sem(bt_book.cleanUpSem) == B_INTERRUPTED);

    return PR_SUCCESS;
}

PR_IMPLEMENT(void)
    PR_ProcessExit (PRIntn status)
{
    exit(status);
}

PRThread *_bt_AttachThread()
{
	PRThread *thread;
	thread_info tInfo;

	/* make sure this thread doesn't already have a PRThread structure */
	PR_ASSERT(tls_get(tls_prThreadSlot) == NULL);

	/* allocate a PRThread structure for this thread */
	thread = PR_NEWZAP(PRThread);
	if (thread == NULL)
	{
		PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
		return NULL;
	}

	/* get the native thread's current state */
	get_thread_info(find_thread(NULL), &tInfo);

	/* initialize new PRThread */
	thread->md.tid = tInfo.thread;
	thread->md.joinSem = B_ERROR;
	thread->priority = _bt_MapNativeToNSPRPriority(tInfo.priority);

	/* attached threads are always non-joinable user threads */
	thread->state = 0;

	/* increment user thread count */
	PR_Lock(bt_book.ml);
	bt_book.threadCount++;
	PR_Unlock(bt_book.ml);

	/* store this thread's PRThread */
	tls_set(tls_prThreadSlot, thread);
	
	/* the thread must call _bt_CleanupThread() before it dies, in order
	   to clean up its PRThread, synchronize with the primordial thread,
	   etc. */
	on_exit_thread(_bt_CleanupThread, NULL);
	
	return thread;
}

deps/mozilla/nsprpub/pr/src/bthreads/objs.mk

# 
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Portable Runtime (NSPR).
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****

# This makefile appends to the variable OBJS the bthread object modules
# that will be part of the nspr20 library.

include $(srcdir)/bthreads/bsrcs.mk

OBJS += $(BTCSRCS:%.c=bthreads/$(OBJDIR)/%.$(OBJ_SUFFIX))

deps/mozilla/nsprpub/pr/src/cplus/rcthread.cpp

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/* RCThread.cpp - C++ wrapper on NSPR */

#include "rcthread.h"
#include "rcinrval.h"

#include <prmem.h>
#include <prlog.h>
#include <stdio.h>
#include <prinit.h>

static RCPrimordialThread *primordial = NULL;

void nas_Root(void *arg)
{
    RCThread *him = (RCThread*)arg;
    while (RCThread::ex_unstarted == him->execution)
        (void)PR_Sleep(PR_INTERVAL_NO_TIMEOUT);  /* wait for Start() */
    him->RootFunction();  /* he gets a self reference */
    if (PR_UNJOINABLE_THREAD == PR_GetThreadState(him->identity))
        delete him;
}  /* nas_Root */

RCThread::~RCThread() { }

RCThread::RCThread(): RCBase() { }

RCThread::RCThread(const RCThread&): RCBase()
{
    PR_NOT_REACHED("Cannot call thread copy constructor");
}  /* RCThread::RCThread */

RCThread::RCThread(
    RCThread::Scope scope, RCThread::State join, PRUint32 stackSize):
    RCBase()
{
    execution = ex_unstarted;
    identity = PR_CreateThread(
        PR_USER_THREAD, nas_Root, this,
        PR_GetThreadPriority(PR_GetCurrentThread()),
        (PRThreadScope)scope, (PRThreadState)join, stackSize);
}  /* RCThread::RCThread */

void RCThread::operator=(const RCThread&)
{
    PR_NOT_REACHED("Cannot call thread assignment operator");
}  /* RCThread::operator= */


PRStatus RCThread::Start()
{
    PRStatus rv;
    /* This is an unsafe check, but not too critical */
    if (RCThread::ex_unstarted == execution)
    {
        execution = RCThread::ex_started;
        rv = PR_Interrupt(identity);
        PR_ASSERT(PR_SUCCESS == rv);
    }
    else
    {
        rv = PR_FAILURE;
        PR_SetError(PR_INVALID_STATE_ERROR, 0);
    }
    return rv;
}  /* RCThread::Start */

PRStatus RCThread::Join()
{
    PRStatus rv;
    if (RCThread::ex_unstarted == execution)
    {
        rv = PR_FAILURE;
        PR_SetError(PR_INVALID_STATE_ERROR, 0);
    }
    else rv = PR_JoinThread(identity);
    if (PR_SUCCESS == rv) delete this;
    return rv;
}  /* RCThread::Join */

PRStatus RCThread::Interrupt()
{
    PRStatus rv;
    if (RCThread::ex_unstarted == execution)
    {
        rv = PR_FAILURE;
        PR_SetError(PR_INVALID_STATE_ERROR, 0);
    }
    else rv = PR_Interrupt(identity);
    return rv;
}  /* RCThread::Interrupt */

void RCThread::ClearInterrupt() { PR_ClearInterrupt(); }

void RCThread::SetPriority(RCThread::Priority new_priority)
    { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); }

PRThread *RCThread::Self()
    { return PR_GetCurrentThread(); }

RCThread::Scope RCThread::GetScope() const
    { return (RCThread::Scope)PR_GetThreadScope(identity); }

RCThread::State RCThread::GetState() const
    { return (RCThread::State)PR_GetThreadState(identity); }

RCThread::Priority RCThread::GetPriority() const
    { return (RCThread::Priority)PR_GetThreadPriority(identity); }
    
static void _rc_PDDestructor(RCThreadPrivateData* privateData)
{
    PR_ASSERT(NULL != privateData);
    privateData->Release();
}

static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor;

PRStatus RCThread::NewPrivateIndex(PRUintn* index)
    { return PR_NewThreadPrivateIndex(index, _tpd_dtor); }

PRStatus RCThread::SetPrivateData(PRUintn index)
    { return PR_SetThreadPrivate(index, NULL); }

PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data)
{
    return PR_SetThreadPrivate(index, data);
}

RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index)
    { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); }

PRStatus RCThread::Sleep(const RCInterval& ticks)
    { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); }

RCPrimordialThread *RCThread::WrapPrimordialThread()
{
    /*
    ** This needs to take more care in insuring that the thread
    ** being wrapped is really the primordial thread. This code
    ** is assuming that the caller is the primordial thread, and
    ** there's nothing to insure that.
    */
    if (NULL == primordial)
    {
        /* it doesn't have to be perfect */
        RCPrimordialThread *me = new RCPrimordialThread();
        PR_ASSERT(NULL != me);
        if (NULL == primordial)
        {
            primordial = me;
            me->execution = RCThread::ex_started;
            me->identity = PR_GetCurrentThread();
        }
        else delete me;  /* somebody beat us to it */
    }
    return primordial;
}  /* RCThread::WrapPrimordialThread */

RCPrimordialThread::RCPrimordialThread(): RCThread() { }

RCPrimordialThread::~RCPrimordialThread() { }

void RCPrimordialThread::RootFunction()
{
    PR_NOT_REACHED("Primordial thread calling root function"); 
}  /* RCPrimordialThread::RootFunction */
 
PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); }

PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count)
{
    PR_SetConcurrency(count);
    return PR_SUCCESS;
}  /* SetVirutalProcessors */

RCThreadPrivateData::RCThreadPrivateData() { }

RCThreadPrivateData::RCThreadPrivateData(
    const RCThreadPrivateData& him) { }

RCThreadPrivateData::~RCThreadPrivateData() { }

/* RCThread.c */

deps/mozilla/nsprpub/pr/src/cplus/rcthread.h

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/* RCThread.h */

#if defined(_RCTHREAD_H)
#else
#define _RCTHREAD_H

#include "rcbase.h"

#include <prthread.h>

class RCInterval;

class PR_IMPLEMENT(RCThreadPrivateData)
{
public:
    RCThreadPrivateData();
    RCThreadPrivateData(const RCThreadPrivateData&);

    virtual ~RCThreadPrivateData();

    virtual void Release() = 0;

};  /* RCThreadPrivateData */

class PR_IMPLEMENT(RCThread): public RCBase
{
public:

    typedef enum 
    {
        local = PR_LOCAL_THREAD, global = PR_GLOBAL_THREAD
    } Scope;

    typedef enum
    {
        joinable = PR_JOINABLE_THREAD, unjoinable = PR_UNJOINABLE_THREAD
    } State;

    typedef enum
    {
        first = PR_PRIORITY_FIRST,
        low = PR_PRIORITY_LOW,
        normal = PR_PRIORITY_NORMAL,
        high = PR_PRIORITY_HIGH,
        urgent = PR_PRIORITY_URGENT,
        last = PR_PRIORITY_LAST
    } Priority;

    /*
     * Create a new thread, providing scope and joinability state.
     */
    RCThread(Scope scope, State state, PRUint32 stackSize=0);

    /*
     * New threads are created in a suspended state. It must be 'started"
     * before it begins execution in the class' defined 'RootFunction()'.
     */
    virtual PRStatus Start();

    /*
     * If a thread is created joinable, then the thread's object exists
     * until join is called. The thread that calls join will block until
     * the target thread returns from it's root function.
     */
    virtual PRStatus Join();
    
    /*
     * The priority of a newly created thread is the same as the creator.
     * The priority may be changed either by the new thread itself, by
     * the creator or any other arbitrary thread.
     */   
    virtual void SetPriority(Priority newPriority);


    /*
     * Interrupt another thread, causing it to stop what it
     * is doing and return with a well known error code.
     */
    virtual PRStatus Interrupt();
    
    /*
     * And in case a thread was interrupted and didn't get a chance
     * to have the notification delivered, a way to cancel the pending
     * status.
     */
    static void ClearInterrupt();
    
    /*
     * Methods to discover the attributes of an existing thread.
     */
    static PRThread *Self();
    Scope GetScope() const;
    State GetState() const;
    Priority GetPriority() const;

    /*
     * Thread private data
     */
    static PRStatus NewPrivateIndex(PRUintn* index);

    /*
     * Getting it - if you want to modify, make a copy
     */
    static RCThreadPrivateData* GetPrivateData(PRUintn index);

    /*
     * Setting it to <empty> - deletes existing data
     */
    static PRStatus SetPrivateData(PRUintn index);

    /*
     * Setting it - runtime will make a copy, freeing old iff necessary
     */
    static PRStatus SetPrivateData(PRUintn index, RCThreadPrivateData* data);

    /*
     * Scheduling control
     */
    static PRStatus Sleep(const RCInterval& ticks);

    friend void nas_Root(void*);
    friend class RCPrimordialThread;
protected:

    /*
     * The instantiator of a class must not call the destructor. The base
     * implementation of Join will, and if the thread is created unjoinable,
     * then the code that called the RootFunction will call the desctructor.
     */
    virtual ~RCThread();

private:

    /*
     * This is where a newly created thread begins execution. Returning
     * from this function is equivalent to terminating the thread.
     */
    virtual void RootFunction() = 0;

    PRThread *identity;

    /* Threads are unstarted until started - pretty startling */
    enum {ex_unstarted, ex_started} execution;

    /* There is no public default constructor or copy constructor */
    RCThread();
    RCThread(const RCThread&);
    
    /* And there is no assignment operator */
    void operator=(const RCThread&);

public:
    static RCPrimordialThread *WrapPrimordialThread();    

 };
 
/*
** class RCPrimordialThread
*/
class PR_IMPLEMENT(RCPrimordialThread): public RCThread
{
public:
    /*
    ** The primordial thread can (optionally) wait for all created
    ** threads to terminate before allowing the process to exit.
    ** Not calling Cleanup() before returning from main() will cause
    ** the immediate termination of the entire process, including
    ** any running threads.
    */
    static PRStatus Cleanup();

    /*
    ** Only the primordial thread is allowed to adjust the number of
    ** virtual processors of the runtime. It's a lame security thing.
    */
    static PRStatus SetVirtualProcessors(PRIntn count=10);

friend class RCThread;
private:
    /*
    ** None other than the runtime can create of destruct
    ** a primordial thread. It is fabricated by the runtime
    ** to wrap the thread that initiated the application.
    */
    RCPrimordialThread();
    ~RCPrimordialThread();
    void RootFunction();
};  /* RCPrimordialThread */

 #endif /* defined(_RCTHREAD_H) */

deps/mozilla/nsprpub/pr/src/cplus/tests/thread.cpp

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/* thread.cpp - a test program */

#include "rcthread.h"

#include <prlog.h>

#include <stdio.h>

class TestThread: public RCThread
{
public:
    TestThread(RCThread::State state, PRIntn count);

    virtual void RootFunction();

protected:
    virtual ~TestThread();

private:
    PRUint32 mydata;
};

TestThread::~TestThread() { }

TestThread::TestThread(RCThread::State state, PRIntn count):
    RCThread(RCThread::global, state, 0) { mydata = count; }

void TestThread::RootFunction()
{
    SetPriority(RCThread::high);
    printf("TestThread::RootFunction %d did it\n", mydata);
}  /* TestThread::RootFunction */

class Foo1
{
public:
    Foo1();
    virtual ~Foo1();

    TestThread *thread;
    PRIntn data;
};

Foo1::Foo1() 
{
    data = 0xafaf;
    thread = new TestThread(RCThread::joinable, 0xafaf);
    thread->Start();
}

Foo1::~Foo1()
{
    PRStatus rv = thread->Join();
    PR_ASSERT(PR_SUCCESS == rv);
}  /* Foo1::~Foo1 */

PRIntn main(PRIntn argc, char **agrv)
{
    PRStatus status;
    PRIntn count = 100;
    RCThread *thread[10];
    while (--count > 0)
    {
        TestThread *thread = new TestThread(RCThread::joinable, count);
        status = thread->Start();  /* have to remember to start it */
        PR_ASSERT(PR_SUCCESS == status);
        status = thread->Join();  /* this should work */
        PR_ASSERT(PR_SUCCESS == status);
    }
    while (++count < 100)
    {
        TestThread *thread = new TestThread(RCThread::unjoinable, count);
        status = thread->Start();  /* have to remember to start it */
        PR_ASSERT(PR_SUCCESS == status);
    }

    {
        Foo1 *foo1 = new Foo1();
        PR_ASSERT(NULL != foo1);
        delete foo1;
    }

    {
        for (count = 0; count < 10; ++count)
        {
            thread[count] = new TestThread( RCThread::joinable, count);
            status = thread[count]->Start();  /* have to remember to start it */
            PR_ASSERT(PR_SUCCESS == status);
        }
        for (count = 0; count < 10; ++count)
        {
            PRStatus rv = thread[count]->Join();
            PR_ASSERT(PR_SUCCESS == rv);
        }
    }

    (void)RCPrimordialThread::Cleanup();

    return 0;
}  /* main */

/* thread.cpp */

deps/mozilla/nsprpub/pr/src/md/unix/pthreads_user.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>


sigset_t ints_off;
pthread_mutex_t	_pr_heapLock;
pthread_key_t current_thread_key;
pthread_key_t current_cpu_key;
pthread_key_t last_thread_key;
pthread_key_t intsoff_key;


PRInt32 _pr_md_pthreads_created, _pr_md_pthreads_failed;
PRInt32 _pr_md_pthreads = 1;

void _MD_EarlyInit(void)
{
extern PRInt32 _nspr_noclock;

	if (pthread_key_create(&current_thread_key, NULL) != 0) {
		perror("pthread_key_create failed");
		exit(1);
	}
	if (pthread_key_create(&current_cpu_key, NULL) != 0) {
		perror("pthread_key_create failed");
		exit(1);
	}
	if (pthread_key_create(&last_thread_key, NULL) != 0) {
		perror("pthread_key_create failed");
		exit(1);
	}
	if (pthread_key_create(&intsoff_key, NULL) != 0) {
		perror("pthread_key_create failed");
		exit(1);
	}

	sigemptyset(&ints_off);
	sigaddset(&ints_off, SIGALRM);
	sigaddset(&ints_off, SIGIO);
	sigaddset(&ints_off, SIGCLD);

	/*
	 * disable clock interrupts
	 */
	_nspr_noclock = 1;

}

void _MD_InitLocks()
{
	if (pthread_mutex_init(&_pr_heapLock, NULL) != 0) {
		perror("pthread_mutex_init failed");
		exit(1);
	}
}

PR_IMPLEMENT(void) _MD_FREE_LOCK(struct _MDLock *lockp)
{
	PRIntn _is;
	PRThread *me = _PR_MD_CURRENT_THREAD();

	if (me && !_PR_IS_NATIVE_THREAD(me))
		_PR_INTSOFF(_is); 
	pthread_mutex_destroy(&lockp->mutex);
	if (me && !_PR_IS_NATIVE_THREAD(me))
		_PR_FAST_INTSON(_is);
}



PR_IMPLEMENT(PRStatus) _MD_NEW_LOCK(struct _MDLock *lockp)
{
    PRStatus rv;
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();	

	if (me && !_PR_IS_NATIVE_THREAD(me))
		_PR_INTSOFF(is);
	rv = pthread_mutex_init(&lockp->mutex, NULL);
	if (me && !_PR_IS_NATIVE_THREAD(me))
		_PR_FAST_INTSON(is);
	return (rv == 0) ? PR_SUCCESS : PR_FAILURE;
}


PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
{
    if (isCurrent) {
	(void) setjmp(CONTEXT(t));
    }
    *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
    return (PRWord *) CONTEXT(t);
}

PR_IMPLEMENT(void)
_MD_SetPriority(_MDThread *thread, PRThreadPriority newPri)
{
	/*
	 * XXX - to be implemented
	 */
    return;
}

PR_IMPLEMENT(PRStatus) _MD_InitThread(struct PRThread *thread)
{
    struct sigaction sigact;

    if (thread->flags & _PR_GLOBAL_SCOPE) {
        thread->md.pthread = pthread_self();
#if 0
		/*
		 * set up SIGUSR1 handler; this is used to save state
		 * during PR_SuspendAll
		 */
		sigact.sa_handler = save_context_and_block;
		sigact.sa_flags = SA_RESTART;
		/*
		 * Must mask clock interrupts
		 */
		sigact.sa_mask = timer_set;
		sigaction(SIGUSR1, &sigact, 0);
#endif
    }

    return PR_SUCCESS;
}

PR_IMPLEMENT(void) _MD_ExitThread(struct PRThread *thread)
{
    if (thread->flags & _PR_GLOBAL_SCOPE) {
        _MD_CLEAN_THREAD(thread);
        _MD_SET_CURRENT_THREAD(NULL);
    }
}

PR_IMPLEMENT(void) _MD_CleanThread(struct PRThread *thread)
{
    if (thread->flags & _PR_GLOBAL_SCOPE) {
		pthread_mutex_destroy(&thread->md.pthread_mutex);
		pthread_cond_destroy(&thread->md.pthread_cond);
    }
}

PR_IMPLEMENT(void) _MD_SuspendThread(struct PRThread *thread)
{
    PRInt32 rv;

    PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&
        _PR_IS_GCABLE_THREAD(thread));
#if 0
	thread->md.suspending_id = getpid();
	rv = kill(thread->md.id, SIGUSR1);
	PR_ASSERT(rv == 0);
	/*
	 * now, block the current thread/cpu until woken up by the suspended
	 * thread from it's SIGUSR1 signal handler
	 */
	blockproc(getpid());
#endif
}

PR_IMPLEMENT(void) _MD_ResumeThread(struct PRThread *thread)
{
    PRInt32 rv;

    PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&
        _PR_IS_GCABLE_THREAD(thread));
#if 0
    rv = unblockproc(thread->md.id);
#endif
}

PR_IMPLEMENT(void) _MD_SuspendCPU(struct _PRCPU *thread)
{
    PRInt32 rv;

#if 0
	cpu->md.suspending_id = getpid();
	rv = kill(cpu->md.id, SIGUSR1);
	PR_ASSERT(rv == 0);
	/*
	 * now, block the current thread/cpu until woken up by the suspended
	 * thread from it's SIGUSR1 signal handler
	 */
	blockproc(getpid());
#endif
}

PR_IMPLEMENT(void) _MD_ResumeCPU(struct _PRCPU *thread)
{
#if 0
	unblockproc(cpu->md.id);
#endif
}


#define PT_NANOPERMICRO 1000UL
#define PT_BILLION 1000000000UL

PR_IMPLEMENT(PRStatus)
_pt_wait(PRThread *thread, PRIntervalTime timeout)
{
int rv;
struct timeval now;
struct timespec tmo;
PRUint32 ticks = PR_TicksPerSecond();


	if (timeout != PR_INTERVAL_NO_TIMEOUT) {
		tmo.tv_sec = timeout / ticks;
		tmo.tv_nsec = timeout - (tmo.tv_sec * ticks);
		tmo.tv_nsec = PR_IntervalToMicroseconds(PT_NANOPERMICRO *
											tmo.tv_nsec);

		/* pthreads wants this in absolute time, off we go ... */
		(void)GETTIMEOFDAY(&now);
		/* that one's usecs, this one's nsecs - grrrr! */
		tmo.tv_sec += now.tv_sec;
		tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);
		tmo.tv_sec += tmo.tv_nsec / PT_BILLION;
		tmo.tv_nsec %= PT_BILLION;
	}

	pthread_mutex_lock(&thread->md.pthread_mutex);
	thread->md.wait--;
	if (thread->md.wait < 0) {
		if (timeout != PR_INTERVAL_NO_TIMEOUT) {
			rv = pthread_cond_timedwait(&thread->md.pthread_cond,
					&thread->md.pthread_mutex, &tmo);
        }
		else
			rv = pthread_cond_wait(&thread->md.pthread_cond,
					&thread->md.pthread_mutex);
		if (rv != 0) {
			thread->md.wait++;
		}
	} else
		rv = 0;
	pthread_mutex_unlock(&thread->md.pthread_mutex);

	return (rv == 0) ? PR_SUCCESS : PR_FAILURE;
}

PR_IMPLEMENT(PRStatus)
_MD_wait(PRThread *thread, PRIntervalTime ticks)
{
    if ( thread->flags & _PR_GLOBAL_SCOPE ) {
		_MD_CHECK_FOR_EXIT();
        if (_pt_wait(thread, ticks) == PR_FAILURE) {
	    	_MD_CHECK_FOR_EXIT();
            /*
             * wait timed out
             */
            _PR_THREAD_LOCK(thread);
            if (thread->wait.cvar) {
                /*
                 * The thread will remove itself from the waitQ
                 * of the cvar in _PR_WaitCondVar
                 */
                thread->wait.cvar = NULL;
                thread->state =  _PR_RUNNING;
                _PR_THREAD_UNLOCK(thread);
            }  else {
        		_pt_wait(thread, PR_INTERVAL_NO_TIMEOUT);
                _PR_THREAD_UNLOCK(thread);
            }
        }
    } else {
		_PR_MD_SWITCH_CONTEXT(thread);
    }
    return PR_SUCCESS;
}

PR_IMPLEMENT(PRStatus)
_MD_WakeupWaiter(PRThread *thread)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRInt32 pid, rv;
    PRIntn is;

	PR_ASSERT(_pr_md_idle_cpus >= 0);
    if (thread == NULL) {
		if (_pr_md_idle_cpus)
        	_MD_Wakeup_CPUs();
    } else if (!_PR_IS_NATIVE_THREAD(thread)) {
		/*
		 * If the thread is on my cpu's runq there is no need to
		 * wakeup any cpus
		 */
		if (!_PR_IS_NATIVE_THREAD(me)) {
			if (me->cpu != thread->cpu) {
				if (_pr_md_idle_cpus)
        			_MD_Wakeup_CPUs();
			}
		} else {
			if (_pr_md_idle_cpus)
        		_MD_Wakeup_CPUs();
		}
    } else {
		PR_ASSERT(_PR_IS_NATIVE_THREAD(thread));
		if (!_PR_IS_NATIVE_THREAD(me))
			_PR_INTSOFF(is);

		pthread_mutex_lock(&thread->md.pthread_mutex);
		thread->md.wait++;
		rv = pthread_cond_signal(&thread->md.pthread_cond);
		PR_ASSERT(rv == 0);
		pthread_mutex_unlock(&thread->md.pthread_mutex);

		if (!_PR_IS_NATIVE_THREAD(me))
			_PR_FAST_INTSON(is);
    } 
    return PR_SUCCESS;
}

/* These functions should not be called for AIX */
PR_IMPLEMENT(void)
_MD_YIELD(void)
{
    PR_NOT_REACHED("_MD_YIELD should not be called for AIX.");
}

PR_IMPLEMENT(PRStatus)
_MD_CreateThread(
    PRThread *thread,
    void (*start) (void *),
    PRThreadPriority priority,
    PRThreadScope scope,
    PRThreadState state,
    PRUint32 stackSize)
{
    PRIntn is;
    int rv;
	PRThread *me = _PR_MD_CURRENT_THREAD();	
	pthread_attr_t attr;

	if (!_PR_IS_NATIVE_THREAD(me))
		_PR_INTSOFF(is);

	if (pthread_mutex_init(&thread->md.pthread_mutex, NULL) != 0) {
		if (!_PR_IS_NATIVE_THREAD(me))
			_PR_FAST_INTSON(is);
        return PR_FAILURE;
	}

	if (pthread_cond_init(&thread->md.pthread_cond, NULL) != 0) {
		pthread_mutex_destroy(&thread->md.pthread_mutex);
		if (!_PR_IS_NATIVE_THREAD(me))
			_PR_FAST_INTSON(is);
        return PR_FAILURE;
	}
    thread->flags |= _PR_GLOBAL_SCOPE;

	pthread_attr_init(&attr); /* initialize attr with default attributes */
	if (pthread_attr_setstacksize(&attr, (size_t) stackSize) != 0) {
		pthread_mutex_destroy(&thread->md.pthread_mutex);
		pthread_cond_destroy(&thread->md.pthread_cond);
		pthread_attr_destroy(&attr);
		if (!_PR_IS_NATIVE_THREAD(me))
			_PR_FAST_INTSON(is);
        return PR_FAILURE;
	}

	thread->md.wait = 0;
    rv = pthread_create(&thread->md.pthread, &attr, start, (void *)thread);
    if (0 == rv) {
        _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_created);
        _MD_ATOMIC_INCREMENT(&_pr_md_pthreads);
		if (!_PR_IS_NATIVE_THREAD(me))
			_PR_FAST_INTSON(is);
        return PR_SUCCESS;
    } else {
		pthread_mutex_destroy(&thread->md.pthread_mutex);
		pthread_cond_destroy(&thread->md.pthread_cond);
		pthread_attr_destroy(&attr);
        _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_failed);
		if (!_PR_IS_NATIVE_THREAD(me))
			_PR_FAST_INTSON(is);
        PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, rv);
        return PR_FAILURE;
    }
}

PR_IMPLEMENT(void)
_MD_InitRunningCPU(struct _PRCPU *cpu)
{
    extern int _pr_md_pipefd[2];

    _MD_unix_init_running_cpu(cpu);
    cpu->md.pthread = pthread_self();
	if (_pr_md_pipefd[0] >= 0) {
    	_PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0];
#ifndef _PR_USE_POLL
    	FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu));
#endif
	}
}


void
_MD_CleanupBeforeExit(void)
{
#if 0
    extern PRInt32    _pr_cpus_exit;

	_pr_irix_exit_now = 1;
    if (_pr_numCPU > 1) {
        /*
         * Set a global flag, and wakeup all cpus which will notice the flag
         * and exit.
         */
        _pr_cpus_exit = getpid();
        _MD_Wakeup_CPUs();
        while(_pr_numCPU > 1) {
            _PR_WAIT_SEM(_pr_irix_exit_sem);
            _pr_numCPU--;
        }
    }
    /*
     * cause global threads on the recycle list to exit
     */
     _PR_DEADQ_LOCK;
     if (_PR_NUM_DEADNATIVE != 0) {
	PRThread *thread;
    	PRCList *ptr;

        ptr = _PR_DEADNATIVEQ.next;
        while( ptr != &_PR_DEADNATIVEQ ) {
        	thread = _PR_THREAD_PTR(ptr);
		_MD_CVAR_POST_SEM(thread);
                ptr = ptr->next;
        } 
     }
     _PR_DEADQ_UNLOCK;
     while(_PR_NUM_DEADNATIVE > 1) {
	_PR_WAIT_SEM(_pr_irix_exit_sem);
	_PR_DEC_DEADNATIVE;
     }
#endif
}

deps/mozilla/nsprpub/pr/src/md/windows/ntthread.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"
#include <process.h>  /* for _beginthreadex() */

/* --- globals ------------------------------------------------ */
PRLock                       *_pr_schedLock = NULL;
_PRInterruptTable             _pr_interruptTable[] = { { 0 } };

BOOL _pr_use_static_tls = TRUE;
__declspec(thread) PRThread  *_pr_current_fiber;
__declspec(thread) PRThread  *_pr_fiber_last_run;
__declspec(thread) _PRCPU    *_pr_current_cpu;
__declspec(thread) PRUintn    _pr_ints_off;
DWORD _pr_currentFiberIndex;
DWORD _pr_lastFiberIndex;
DWORD _pr_currentCPUIndex;
DWORD _pr_intsOffIndex;

_MDLock                       _nt_idleLock;
PRCList                       _nt_idleList;
PRUint32                        _nt_idleCount;

extern __declspec(thread) PRThread *_pr_io_restarted_io;
extern DWORD _pr_io_restartedIOIndex;

/* Must check the restarted_io *before* decrementing no_sched to 0 */
#define POST_SWITCH_WORK() \
    PR_BEGIN_MACRO \
        PRThread *restarted_io = \
            (_pr_use_static_tls ? _pr_io_restarted_io \
            : (PRThread *) TlsGetValue(_pr_io_restartedIOIndex)); \
        if (restarted_io) { \
            _nt_handle_restarted_io(restarted_io); \
        } \
        _PR_MD_LAST_THREAD()->no_sched = 0; \
    PR_END_MACRO

void
_nt_handle_restarted_io(PRThread *restarted_io)
{
    /* After the switch we can resume an IO if needed.
     * XXXMB - this needs to be done in create thread, since that could
     * be the result for a context switch too..
     */
    PR_ASSERT(restarted_io->io_suspended == PR_TRUE);
    PR_ASSERT(restarted_io->md.thr_bound_cpu == restarted_io->cpu);

    _PR_THREAD_LOCK(restarted_io);
    if (restarted_io->io_pending == PR_FALSE) {

        /* The IO already completed, put us back on the runq. */
        int pri = restarted_io->priority;

        restarted_io->state = _PR_RUNNABLE;
        _PR_RUNQ_LOCK(restarted_io->cpu);
        _PR_ADD_RUNQ(restarted_io, restarted_io->cpu, pri);
        _PR_RUNQ_UNLOCK(restarted_io->cpu);
    } else {
        _PR_SLEEPQ_LOCK(restarted_io->cpu);
        _PR_ADD_SLEEPQ(restarted_io, restarted_io->sleep);
        _PR_SLEEPQ_UNLOCK(restarted_io->cpu);
    }
    restarted_io->io_suspended = PR_FALSE;
    restarted_io->md.thr_bound_cpu = NULL;

    _PR_THREAD_UNLOCK(restarted_io);

    if (_pr_use_static_tls) {
        _pr_io_restarted_io = NULL;
    } else {
        TlsSetValue(_pr_io_restartedIOIndex, NULL);
    }
}

void
_PR_MD_EARLY_INIT()
{
    _MD_NEW_LOCK( &_nt_idleLock );
    _nt_idleCount = 0;
    PR_INIT_CLIST(&_nt_idleList);

#if 0
    /* Make the clock tick at least once per millisecond */
    if ( timeBeginPeriod(1) == TIMERR_NOCANDO) {
        /* deep yoghurt; clock doesn't tick fast enough! */
        PR_ASSERT(0);
    }
#endif

    if (!_pr_use_static_tls) {
        _pr_currentFiberIndex = TlsAlloc();
        _pr_lastFiberIndex = TlsAlloc();
        _pr_currentCPUIndex = TlsAlloc();
        _pr_intsOffIndex = TlsAlloc();
        _pr_io_restartedIOIndex = TlsAlloc();
    }
}

void _PR_MD_CLEANUP_BEFORE_EXIT(void)
{
    _PR_NT_FreeSids();

    WSACleanup();

    if (!_pr_use_static_tls) {
        TlsFree(_pr_currentFiberIndex);
        TlsFree(_pr_lastFiberIndex);
        TlsFree(_pr_currentCPUIndex);
        TlsFree(_pr_intsOffIndex);
        TlsFree(_pr_io_restartedIOIndex);
    }
}

PRStatus
_PR_MD_INIT_THREAD(PRThread *thread)
{
    thread->md.overlapped.ioModel = _MD_BlockingIO;
    thread->md.overlapped.data.mdThread = &thread->md;

    if (thread->flags & _PR_GLOBAL_SCOPE) {
        if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
            /*
            ** Warning:
            ** --------
            ** NSPR requires a real handle to every thread.
            ** GetCurrentThread() returns a pseudo-handle which
            ** is not suitable for some thread operations (e.g.,
            ** suspending).  Therefore, get a real handle from
            ** the pseudo handle via DuplicateHandle(...)
            */
            DuplicateHandle(
                    GetCurrentProcess(),     /* Process of source handle */
                    GetCurrentThread(),      /* Pseudo Handle to dup */
                    GetCurrentProcess(),     /* Process of handle */
                    &(thread->md.handle),    /* resulting handle */
                    0L,                      /* access flags */
                    FALSE,                   /* Inheritable */
                    DUPLICATE_SAME_ACCESS);  /* Options */
        }

        /* Create the blocking IO semaphore */
        thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL);
        if (thread->md.blocked_sema == NULL) {
            return PR_FAILURE;
        }
		if (_native_threads_only) {
			/* Create the blocking IO semaphore */
			thread->md.thr_event = CreateEvent(NULL, TRUE, FALSE, NULL);
			if (thread->md.thr_event == NULL) {
				return PR_FAILURE;
			}
		}
    }

    return PR_SUCCESS;
}

static unsigned __stdcall
pr_root(void *arg)
{
    PRThread *thread = (PRThread *)arg;
    thread->md.start(thread);
    return 0;
}

PRStatus 
_PR_MD_CREATE_THREAD(PRThread *thread, 
                  void (*start)(void *), 
                  PRThreadPriority priority, 
                  PRThreadScope scope, 
                  PRThreadState state, 
                  PRUint32 stackSize)
{

    thread->md.start = start;
    thread->md.handle = (HANDLE) _beginthreadex(
                    NULL,
                    thread->stack->stackSize,
                    pr_root,
                    (void *)thread,
                    CREATE_SUSPENDED,
                    &(thread->id));
    if(!thread->md.handle) {
        PRErrorCode prerror;
        thread->md.fiber_last_error = GetLastError();
        switch (errno) {
            case ENOMEM:
                prerror = PR_OUT_OF_MEMORY_ERROR;
                break;
            case EAGAIN:
                prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
                break;
            case EINVAL:
                prerror = PR_INVALID_ARGUMENT_ERROR;
                break;
            default:
                prerror = PR_UNKNOWN_ERROR;
        }
        PR_SetError(prerror, errno);
        return PR_FAILURE;
    }

    thread->md.id = thread->id;
    /*
     * On windows, a thread is created with a thread priority of
     * THREAD_PRIORITY_NORMAL.
     */
    if (priority != PR_PRIORITY_NORMAL) {
        _PR_MD_SET_PRIORITY(&(thread->md), priority);
    }

    /* Activate the thread */
    if ( ResumeThread( thread->md.handle ) != -1)
        return PR_SUCCESS;

    PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
    return PR_FAILURE;
}

void
_PR_MD_JOIN_THREAD(_MDThread *md)
{
    DWORD rv;

    rv = WaitForSingleObject(md->handle, INFINITE);
    PR_ASSERT(WAIT_OBJECT_0 == rv);
}

void
_PR_MD_END_THREAD(void)
{
    _endthreadex(0);
}

void    
_PR_MD_YIELD(void)
{
    /* Can NT really yield at all? */
    Sleep(0);
}

void     
_PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
{
    int nativePri;
    BOOL rv;

    if (newPri < PR_PRIORITY_FIRST) {
        newPri = PR_PRIORITY_FIRST;
    } else if (newPri > PR_PRIORITY_LAST) {
        newPri = PR_PRIORITY_LAST;
    }
    switch (newPri) {
        case PR_PRIORITY_LOW:
            nativePri = THREAD_PRIORITY_BELOW_NORMAL;
            break;
        case PR_PRIORITY_NORMAL:
            nativePri = THREAD_PRIORITY_NORMAL;
            break;
        case PR_PRIORITY_HIGH:
            nativePri = THREAD_PRIORITY_ABOVE_NORMAL;
            break;
        case PR_PRIORITY_URGENT:
            nativePri = THREAD_PRIORITY_HIGHEST;
    }
    rv = SetThreadPriority(thread->handle, nativePri);
    PR_ASSERT(rv);
    if (!rv) {
	PR_LOG(_pr_thread_lm, PR_LOG_MIN,
                ("PR_SetThreadPriority: can't set thread priority\n"));
    }
    return;
}

void
_PR_MD_CLEAN_THREAD(PRThread *thread)
{
    BOOL rv;

    if (thread->md.acceptex_buf) {
        PR_DELETE(thread->md.acceptex_buf);
    }

    if (thread->md.xmit_bufs) {
        PR_DELETE(thread->md.xmit_bufs);
    }

    if (thread->md.blocked_sema) {
        rv = CloseHandle(thread->md.blocked_sema);
        PR_ASSERT(rv);
        thread->md.blocked_sema = 0;
    }
	if (_native_threads_only) {
		if (thread->md.thr_event) {
			rv = CloseHandle(thread->md.thr_event);
			PR_ASSERT(rv);
			thread->md.thr_event = 0;
		}
	}

    if (thread->md.handle) {
        rv = CloseHandle(thread->md.handle);
        PR_ASSERT(rv);
        thread->md.handle = 0;
    }

    /* Don't call DeleteFiber on current fiber or we'll kill the whole thread.
     * Don't call free(thread) until we've switched off the thread.
     * So put this fiber (or thread) on a list to be deleted by the idle
     * fiber next time we have a chance.
     */
    if (!(thread->flags & (_PR_ATTACHED|_PR_GLOBAL_SCOPE))) {
        _MD_LOCK(&_nt_idleLock);
        _nt_idleCount++;
        PR_APPEND_LINK(&thread->links, &_nt_idleList);
        _MD_UNLOCK(&_nt_idleLock);
    }
}

void
_PR_MD_EXIT_THREAD(PRThread *thread)
{
    BOOL rv;

    if (thread->md.acceptex_buf) {
        PR_DELETE(thread->md.acceptex_buf);
    }

    if (thread->md.xmit_bufs) {
        PR_DELETE(thread->md.xmit_bufs);
    }

    if (thread->md.blocked_sema) {
        rv = CloseHandle(thread->md.blocked_sema);
        PR_ASSERT(rv);
        thread->md.blocked_sema = 0;
    }

	if (_native_threads_only) {
		if (thread->md.thr_event) {
			rv = CloseHandle(thread->md.thr_event);
			PR_ASSERT(rv);
			thread->md.thr_event = 0;
		}
	}

    if (thread->md.handle) {
        rv = CloseHandle(thread->md.handle);
        PR_ASSERT(rv);
        thread->md.handle = 0;
    }

    if (thread->flags & _PR_GLOBAL_SCOPE) {
        _MD_SET_CURRENT_THREAD(NULL);
    }
}


void
_PR_MD_EXIT(PRIntn status)
{
    _exit(status);
}

#ifdef HAVE_FIBERS

void
_pr_fiber_mainline(void *unused) 
{
    PRThread *fiber = _PR_MD_CURRENT_THREAD();

    POST_SWITCH_WORK();

    fiber->md.fiber_fn(fiber->md.fiber_arg);
}

PRThread *_PR_MD_CREATE_USER_THREAD(
    PRUint32 stacksize, void (*start)(void *), void *arg)
{
    PRThread *thread;

    if ( (thread = PR_NEW(PRThread)) == NULL ) {
        return NULL;
    }
    
    memset(thread, 0, sizeof(PRThread));
    thread->md.fiber_fn = start;
    thread->md.fiber_arg = arg;
    thread->md.fiber_stacksize = stacksize;
    return thread;
}

void
_PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *thread)
{
    thread->md.fiber_id = ConvertThreadToFiber(NULL);
    PR_ASSERT(thread->md.fiber_id);
    _MD_SET_CURRENT_THREAD(thread);
    _MD_SET_LAST_THREAD(thread);
    thread->no_sched = 1;
    return;
}

void
_PR_MD_INIT_CONTEXT(PRThread *thread, char *top, void (*start) (void), PRBool *status)
{
    thread->md.fiber_fn = (void (*)(void *))start;
    thread->md.fiber_id = CreateFiber(thread->md.fiber_stacksize, 
        (LPFIBER_START_ROUTINE)_pr_fiber_mainline, NULL);
    if (thread->md.fiber_id != 0)
        *status = PR_TRUE;
    else {
        DWORD oserror = GetLastError();
        PRErrorCode prerror;
        if (oserror == ERROR_NOT_ENOUGH_MEMORY) {
            prerror = PR_OUT_OF_MEMORY_ERROR;
        } else {
            prerror = PR_UNKNOWN_ERROR;
        }
        PR_SetError(prerror, oserror);
        *status = PR_FALSE;
    }
}

void
_PR_MD_SWITCH_CONTEXT(PRThread *thread)
{
    PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );

    thread->md.fiber_last_error = GetLastError();
    _PR_Schedule();
}

void
_PR_MD_RESTORE_CONTEXT(PRThread *thread)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );

    /* The user-level code for yielding will happily add ourselves to the runq
     * and then switch to ourselves; the NT fibers can't handle switching to 
     * ourselves.
     */
    if (thread != me) {
        SetLastError(thread->md.fiber_last_error);
        _MD_SET_CURRENT_THREAD(thread);
        _PR_MD_SET_LAST_THREAD(me);
        thread->no_sched = 1;
        SwitchToFiber(thread->md.fiber_id);
        POST_SWITCH_WORK();
    }
}


#endif /* HAVE_FIBERS */

PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask )
{
    int rv;

    rv = SetThreadAffinityMask(thread->md.handle, mask);

    return rv?0:-1;
}

PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask)
{
    PRInt32 rv, system_mask;

    rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask);
    
    return rv?0:-1;
}

void 
_PR_MD_SUSPEND_CPU(_PRCPU *cpu) 
{
    _PR_MD_SUSPEND_THREAD(cpu->thread);
}

void
_PR_MD_RESUME_CPU(_PRCPU *cpu)
{
    _PR_MD_RESUME_THREAD(cpu->thread);
}

void
_PR_MD_SUSPEND_THREAD(PRThread *thread)
{
    if (_PR_IS_NATIVE_THREAD(thread)) {
        /*
        ** There seems to be some doubt about whether or not SuspendThread
        ** is a synchronous function. The test afterwards is to help veriry
        ** that it is, which is what Microsoft says it is.
        */
        PRUintn rv = SuspendThread(thread->md.handle);
        PR_ASSERT(0xffffffffUL != rv);
    }
}

void
_PR_MD_RESUME_THREAD(PRThread *thread)
{
    if (_PR_IS_NATIVE_THREAD(thread)) {
        ResumeThread(thread->md.handle);
    }
}

PRThread*
_MD_CURRENT_THREAD(void)
{
PRThread *thread;

	thread = _MD_GET_ATTACHED_THREAD();

   	if (NULL == thread) {
		thread = _PRI_AttachThread(
            PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
	}
	PR_ASSERT(thread != NULL);
	return thread;
}

deps/mozilla/nsprpub/pr/src/pthreads/


        

deps/mozilla/nsprpub/pr/src/pthreads/.cvsignore

Makefile

deps/mozilla/nsprpub/pr/src/pthreads/Makefile.in

# 
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Portable Runtime (NSPR).
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****


#! gmake

MOD_DEPTH	= ../../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(MOD_DEPTH)/config/autoconf.mk

include $(topsrcdir)/config/config.mk

# Disable optimization of the nspr on SunOS4.1.3
ifeq ($(OS_ARCH),SunOS)
ifeq ($(OS_RELEASE),4.1.3_U1)
OPTIMIZER =
endif
endif

CSRCS = \
	ptio.c \
	ptsynch.c \
	ptthread.c \
	ptmisc.c \
	$(NULL)

TARGETS	= $(OBJS)

INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private

DEFINES	+= -D_NSPR_BUILD_

include $(topsrcdir)/config/rules.mk

export:: $(TARGETS)


deps/mozilla/nsprpub/pr/src/pthreads/ptio.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
** File:   ptio.c
** Descritpion:  Implemenation of I/O methods for pthreads
*/

#if defined(_PR_PTHREADS)

#if defined(_PR_POLL_WITH_SELECT)
#if !(defined(HPUX) && defined(_USE_BIG_FDS))
/* set fd limit for select(), before including system header files */
#define FD_SETSIZE (16 * 1024)
#endif
#endif

#include <pthread.h>
#include <string.h>  /* for memset() */
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#if defined(DARWIN)
#include <sys/utsname.h> /* for uname */
#endif
#if defined(SOLARIS) || defined(UNIXWARE)
#include <sys/filio.h>  /* to pick up FIONREAD */
#endif
#ifdef _PR_POLL_AVAILABLE
#include <poll.h>
#endif
#ifdef AIX
/* To pick up sysconf() */
#include <unistd.h>
#include <dlfcn.h>  /* for dlopen */
#else
/* To pick up getrlimit() etc. */
#include <sys/time.h>
#include <sys/resource.h>
#endif

#ifdef SOLARIS
/*
 * Define HAVE_SENDFILEV if the system has the sendfilev() system call.
 * Code built this way won't run on a system without sendfilev().
 * We can define HAVE_SENDFILEV by default when the minimum release
 * of Solaris that NSPR supports has sendfilev().
 */
#ifdef HAVE_SENDFILEV

#include <sys/sendfile.h>

#define SOLARIS_SENDFILEV(a, b, c, d) sendfilev((a), (b), (c), (d))

#else

#include <dlfcn.h>  /* for dlopen */

/*
 * Match the definitions in <sys/sendfile.h>.
 */
typedef struct sendfilevec {
    int sfv_fd;       /* input fd */
    uint_t sfv_flag;  /* flags */
    off_t sfv_off;    /* offset to start reading from */
    size_t sfv_len;   /* amount of data */
} sendfilevec_t;

#define SFV_FD_SELF (-2)

/*
 * extern ssize_t sendfilev(int, const struct sendfilevec *, int, size_t *);
 */
static ssize_t (*pt_solaris_sendfilev_fptr)() = NULL;

#define SOLARIS_SENDFILEV(a, b, c, d) \
        (*pt_solaris_sendfilev_fptr)((a), (b), (c), (d))

#endif /* HAVE_SENDFILEV */
#endif /* SOLARIS */

/*
 * The send_file() system call is available in AIX 4.3.2 or later.
 * If this file is compiled on an older AIX system, it attempts to
 * look up the send_file symbol at run time to determine whether
 * we can use the faster PR_SendFile/PR_TransmitFile implementation based on
 * send_file().  On AIX 4.3.2 or later, we can safely skip this
 * runtime function dispatching and just use the send_file based
 * implementation.
 */
#ifdef AIX
#ifdef SF_CLOSE
#define HAVE_SEND_FILE
#endif

#ifdef HAVE_SEND_FILE

#define AIX_SEND_FILE(a, b, c) send_file(a, b, c)

#else /* HAVE_SEND_FILE */

/*
 * The following definitions match those in <sys/socket.h>
 * on AIX 4.3.2.
 */

/*
 * Structure for the send_file() system call
 */
struct sf_parms {
    /* --------- header parms ---------- */
    void      *header_data;         /* Input/Output. Points to header buf */
    uint_t    header_length;        /* Input/Output. Length of the header */
    /* --------- file parms ------------ */
    int       file_descriptor;      /* Input. File descriptor of the file */
    unsigned long long file_size;   /* Output. Size of the file */
    unsigned long long file_offset; /* Input/Output. Starting offset */
    long long file_bytes;           /* Input/Output. no. of bytes to send */
    /* --------- trailer parms --------- */
    void      *trailer_data;        /* Input/Output. Points to trailer buf */
    uint_t    trailer_length;       /* Input/Output. Length of the trailer */
    /* --------- return info ----------- */
    unsigned long long bytes_sent;  /* Output. no. of bytes sent */
};

/*
 * Flags for the send_file() system call
 */
#define SF_CLOSE        0x00000001      /* close the socket after completion */
#define SF_REUSE        0x00000002      /* reuse socket. not supported */
#define SF_DONT_CACHE   0x00000004      /* don't apply network buffer cache */
#define SF_SYNC_CACHE   0x00000008      /* sync/update network buffer cache */

/*
 * prototype: size_t send_file(int *, struct sf_parms *, uint_t);
 */
static ssize_t (*pt_aix_sendfile_fptr)() = NULL;

#define AIX_SEND_FILE(a, b, c) (*pt_aix_sendfile_fptr)(a, b, c)

#endif /* HAVE_SEND_FILE */
#endif /* AIX */

#ifdef LINUX
#include <sys/sendfile.h>
#endif

#include "primpl.h"

#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>  /* TCP_NODELAY, TCP_MAXSEG */
#endif

#ifdef LINUX
/* TCP_CORK is not defined in <netinet/tcp.h> on Red Hat Linux 6.0 */
#ifndef TCP_CORK
#define TCP_CORK 3
#endif
#endif

#ifdef _PR_IPV6_V6ONLY_PROBE
static PRBool _pr_ipv6_v6only_on_by_default;
#endif

#if (defined(HPUX) && !defined(HPUX10_30) && !defined(HPUX11))
#define _PRSelectFdSetArg_t int *
#elif defined(AIX4_1)
#define _PRSelectFdSetArg_t void *
#elif defined(IRIX) || (defined(AIX) && !defined(AIX4_1)) \
    || defined(OSF1) || defined(SOLARIS) \
    || defined(HPUX10_30) || defined(HPUX11) \
    || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
    || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
    || defined(BSDI) || defined(NTO) || defined(DARWIN) \
    || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN)
#define _PRSelectFdSetArg_t fd_set *
#else
#error "Cannot determine architecture"
#endif

static PRFileDesc *pt_SetMethods(
    PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported);

static PRLock *_pr_flock_lock;  /* For PR_LockFile() etc. */
static PRCondVar *_pr_flock_cv;  /* For PR_LockFile() etc. */
static PRLock *_pr_rename_lock;  /* For PR_Rename() */

/**************************************************************************/

/* These two functions are only used in assertions. */
#if defined(DEBUG)

PRBool IsValidNetAddr(const PRNetAddr *addr)
{
    if ((addr != NULL)
            && (addr->raw.family != AF_UNIX)
            && (addr->raw.family != PR_AF_INET6)
            && (addr->raw.family != AF_INET)) {
        return PR_FALSE;
    }
    return PR_TRUE;
}

static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
{
    /*
     * The definition of the length of a Unix domain socket address
     * is not uniform, so we don't check it.
     */
    if ((addr != NULL)
            && (addr->raw.family != AF_UNIX)
            && (PR_NETADDR_SIZE(addr) != addr_len)) {
#if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1
        /*
         * In glibc 2.1, struct sockaddr_in6 is 24 bytes.  In glibc 2.2
         * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id
         * field and is 28 bytes.  It is possible for socket functions
         * to return an addr_len greater than sizeof(struct sockaddr_in6).
         * We need to allow that.  (Bugzilla bug #77264)
         */
        if ((PR_AF_INET6 == addr->raw.family)
                && (sizeof(addr->ipv6) == addr_len)) {
            return PR_TRUE;
        }
#endif
        return PR_FALSE;
    }
    return PR_TRUE;
}

#endif /* DEBUG */

/*****************************************************************************/
/************************* I/O Continuation machinery ************************/
/*****************************************************************************/

/*
 * The polling interval defines the maximum amount of time that a thread
 * might hang up before an interrupt is noticed.
 */
#define PT_DEFAULT_POLL_MSEC 5000
#if defined(_PR_POLL_WITH_SELECT)
#define PT_DEFAULT_SELECT_SEC (PT_DEFAULT_POLL_MSEC/PR_MSEC_PER_SEC)
#define PT_DEFAULT_SELECT_USEC							\
		((PT_DEFAULT_POLL_MSEC % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC)
#endif

/*
 * pt_SockLen is the type for the length of a socket address
 * structure, used in the address length argument to bind,
 * connect, accept, getsockname, getpeername, etc.  Posix.1g
 * defines this type as socklen_t.  It is size_t or int on
 * most current systems.
 */
#if defined(HAVE_SOCKLEN_T) \
    || (defined(__GLIBC__) && __GLIBC__ >= 2)
typedef socklen_t pt_SockLen;
#elif (defined(AIX) && !defined(AIX4_1)) 
typedef PRSize pt_SockLen;
#else
typedef PRIntn pt_SockLen;
#endif

typedef struct pt_Continuation pt_Continuation;
typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revents);

typedef enum pr_ContuationStatus
{
    pt_continuation_pending,
    pt_continuation_done
} pr_ContuationStatus;

struct pt_Continuation
{
    /* The building of the continuation operation */
    ContinuationFn function;                /* what function to continue */
    union { PRIntn osfd; } arg1;            /* #1 - the op's fd */
    union { void* buffer; } arg2;           /* #2 - primary transfer buffer */
    union {
        PRSize amount;                      /* #3 - size of 'buffer', or */
        pt_SockLen *addr_len;                  /*    - length of address */
#ifdef HPUX11
        /*
         * For sendfile()
         */
		struct file_spec {		
        	off_t offset;                       /* offset in file to send */
        	size_t nbytes;                      /* length of file data to send */
        	size_t st_size;                     /* file size */
		} file_spec;
#endif
    } arg3;
    union { PRIntn flags; } arg4;           /* #4 - read/write flags */
    union { PRNetAddr *addr; } arg5;        /* #5 - send/recv address */

#ifdef HPUX11
    /*
     * For sendfile()
     */
    int filedesc;                           /* descriptor of file to send */
    int nbytes_to_send;                     /* size of header and file */
#endif  /* HPUX11 */
    
#ifdef SOLARIS
    /*
     * For sendfilev()
     */
    int nbytes_to_send;                     /* size of header and file */
#endif  /* SOLARIS */

#ifdef LINUX
    /*
     * For sendfile()
     */
    int in_fd;                              /* descriptor of file to send */
    off_t offset;
    size_t count;
#endif  /* LINUX */
 
    PRIntervalTime timeout;                 /* client (relative) timeout */

    PRInt16 event;                           /* flags for poll()'s events */

    /*
    ** The representation and notification of the results of the operation.
    ** These function can either return an int return code or a pointer to
    ** some object.
    */
    union { PRSize code; void *object; } result;

    PRIntn syserrno;                        /* in case it failed, why (errno) */
    pr_ContuationStatus status;             /* the status of the operation */
};

#if defined(DEBUG)

PTDebug pt_debug;  /* this is shared between several modules */

PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
{
    PTDebug stats;
    char buffer[100];
    PRExplodedTime tod;
    PRInt64 elapsed, aMil;
    stats = pt_debug;  /* a copy */
    PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod);
    (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);

    LL_SUB(elapsed, PR_Now(), stats.timeStarted);
    LL_I2L(aMil, 1000000);
    LL_DIV(elapsed, elapsed, aMil);
    
    if (NULL != msg) PR_fprintf(debug_out, "%s", msg);
    PR_fprintf(
        debug_out, "\tstarted: %s[%lld]\n", buffer, elapsed);
    PR_fprintf(
        debug_out, "\tlocks [created: %u, destroyed: %u]\n",
        stats.locks_created, stats.locks_destroyed);
    PR_fprintf(
        debug_out, "\tlocks [acquired: %u, released: %u]\n",
        stats.locks_acquired, stats.locks_released);
    PR_fprintf(
        debug_out, "\tcvars [created: %u, destroyed: %u]\n",
        stats.cvars_created, stats.cvars_destroyed);
    PR_fprintf(
        debug_out, "\tcvars [notified: %u, delayed_delete: %u]\n",
        stats.cvars_notified, stats.delayed_cv_deletes);
}  /* PT_FPrintStats */

#else

PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
{
    /* do nothing */
}  /* PT_FPrintStats */

#endif  /* DEBUG */

#if defined(_PR_POLL_WITH_SELECT)
/*
 * OSF1 and HPUX report the POLLHUP event for a socket when the
 * shutdown(SHUT_WR) operation is called for the remote end, even though
 * the socket is still writeable. Use select(), instead of poll(), to
 * workaround this problem.
 */
static void pt_poll_now_with_select(pt_Continuation *op)
{
    PRInt32 msecs;
	fd_set rd, wr, *rdp, *wrp;
	struct timeval tv;
	PRIntervalTime epoch, now, elapsed, remaining;
	PRBool wait_for_remaining;
    PRThread *self = PR_GetCurrentThread();
    
	PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
	PR_ASSERT(op->arg1.osfd < FD_SETSIZE);

    switch (op->timeout) {
        case PR_INTERVAL_NO_TIMEOUT:
			tv.tv_sec = PT_DEFAULT_SELECT_SEC;
			tv.tv_usec = PT_DEFAULT_SELECT_USEC;
			do
			{
				PRIntn rv;

				if (op->event & POLLIN) {
					FD_ZERO(&rd);
					FD_SET(op->arg1.osfd, &rd);
					rdp = &rd;
				} else
					rdp = NULL;
				if (op->event & POLLOUT) {
					FD_ZERO(&wr);
					FD_SET(op->arg1.osfd, &wr);
					wrp = &wr;
				} else
					wrp = NULL;

				rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);

				if (_PT_THREAD_INTERRUPTED(self))
				{
					self->state &= ~PT_THREAD_ABORTED;
					op->result.code = -1;
					op->syserrno = EINTR;
					op->status = pt_continuation_done;
					return;
				}

				if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN)))
					continue; /* go around the loop again */

				if (rv > 0)
				{
					PRInt16 revents = 0;

					if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd))
						revents |= POLLIN;
					if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr))
						revents |= POLLOUT;
						
					if (op->function(op, revents))
						op->status = pt_continuation_done;
				} else if (rv == -1) {
					op->result.code = -1;
					op->syserrno = errno;
					op->status = pt_continuation_done;
				}
				/* else, select timed out */
			} while (pt_continuation_done != op->status);
			break;
        default:
            now = epoch = PR_IntervalNow();
            remaining = op->timeout;
			do
			{
				PRIntn rv;

				if (op->event & POLLIN) {
					FD_ZERO(&rd);
					FD_SET(op->arg1.osfd, &rd);
					rdp = &rd;
				} else
					rdp = NULL;
				if (op->event & POLLOUT) {
					FD_ZERO(&wr);
					FD_SET(op->arg1.osfd, &wr);
					wrp = &wr;
				} else
					wrp = NULL;

    			wait_for_remaining = PR_TRUE;
    			msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
				if (msecs > PT_DEFAULT_POLL_MSEC) {
					wait_for_remaining = PR_FALSE;
					msecs = PT_DEFAULT_POLL_MSEC;
				}
				tv.tv_sec = msecs/PR_MSEC_PER_SEC;
				tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
				rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);

				if (_PT_THREAD_INTERRUPTED(self))
				{
					self->state &= ~PT_THREAD_ABORTED;
					op->result.code = -1;
					op->syserrno = EINTR;
					op->status = pt_continuation_done;
					return;
				}

				if (rv > 0) {
					PRInt16 revents = 0;

					if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd))
						revents |= POLLIN;
					if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr))
						revents |= POLLOUT;
						
					if (op->function(op, revents))
						op->status = pt_continuation_done;

				} else if ((rv == 0) ||
						((errno == EINTR) || (errno == EAGAIN))) {
					if (rv == 0) {	/* select timed out */
						if (wait_for_remaining)
							now += remaining;
						else
							now += PR_MillisecondsToInterval(msecs);
					} else
						now = PR_IntervalNow();
					elapsed = (PRIntervalTime) (now - epoch);
					if (elapsed >= op->timeout) {
						op->result.code = -1;
						op->syserrno = ETIMEDOUT;
						op->status = pt_continuation_done;
					} else
						remaining = op->timeout - elapsed;
				} else {
					op->result.code = -1;
					op->syserrno = errno;
					op->status = pt_continuation_done;
				}
			} while (pt_continuation_done != op->status);
            break;
    }

}  /* pt_poll_now_with_select */

#endif	/* _PR_POLL_WITH_SELECT */

static void pt_poll_now(pt_Continuation *op)
{
    PRInt32 msecs;
	PRIntervalTime epoch, now, elapsed, remaining;
	PRBool wait_for_remaining;
    PRThread *self = PR_GetCurrentThread();
    
	PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
#if defined (_PR_POLL_WITH_SELECT)
	/*
 	 * If the fd is small enough call the select-based poll operation
	 */
	if (op->arg1.osfd < FD_SETSIZE) {
		pt_poll_now_with_select(op);
		return;
	}
#endif

    switch (op->timeout) {
        case PR_INTERVAL_NO_TIMEOUT:
			msecs = PT_DEFAULT_POLL_MSEC;
			do
			{
				PRIntn rv;
				struct pollfd tmp_pfd;

				tmp_pfd.revents = 0;
				tmp_pfd.fd = op->arg1.osfd;
				tmp_pfd.events = op->event;

				rv = poll(&tmp_pfd, 1, msecs);
				
				if (_PT_THREAD_INTERRUPTED(self))
				{
					self->state &= ~PT_THREAD_ABORTED;
					op->result.code = -1;
					op->syserrno = EINTR;
					op->status = pt_continuation_done;
					return;
				}

				if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN)))
					continue; /* go around the loop again */

				if (rv > 0)
				{
					PRInt16 events = tmp_pfd.events;
					PRInt16 revents = tmp_pfd.revents;

					if ((revents & POLLNVAL)  /* busted in all cases */
					|| ((events & POLLOUT) && (revents & POLLHUP)))
						/* write op & hup */
					{
						op->result.code = -1;
						if (POLLNVAL & revents) op->syserrno = EBADF;
						else if (POLLHUP & revents) op->syserrno = EPIPE;
						op->status = pt_continuation_done;
					} else {
						if (op->function(op, revents))
							op->status = pt_continuation_done;
					}
				} else if (rv == -1) {
					op->result.code = -1;
					op->syserrno = errno;
					op->status = pt_continuation_done;
				}
				/* else, poll timed out */
			} while (pt_continuation_done != op->status);
			break;
        default:
            now = epoch = PR_IntervalNow();
            remaining = op->timeout;
			do
			{
				PRIntn rv;
				struct pollfd tmp_pfd;

				tmp_pfd.revents = 0;
				tmp_pfd.fd = op->arg1.osfd;
				tmp_pfd.events = op->event;

    			wait_for_remaining = PR_TRUE;
    			msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
				if (msecs > PT_DEFAULT_POLL_MSEC)
				{
					wait_for_remaining = PR_FALSE;
					msecs = PT_DEFAULT_POLL_MSEC;
				}
				rv = poll(&tmp_pfd, 1, msecs);
				
				if (_PT_THREAD_INTERRUPTED(self))
				{
					self->state &= ~PT_THREAD_ABORTED;
					op->result.code = -1;
					op->syserrno = EINTR;
					op->status = pt_continuation_done;
					return;
				}

				if (rv > 0)
				{
					PRInt16 events = tmp_pfd.events;
					PRInt16 revents = tmp_pfd.revents;

					if ((revents & POLLNVAL)  /* busted in all cases */
						|| ((events & POLLOUT) && (revents & POLLHUP))) 
											/* write op & hup */
					{
						op->result.code = -1;
						if (POLLNVAL & revents) op->syserrno = EBADF;
						else if (POLLHUP & revents) op->syserrno = EPIPE;
						op->status = pt_continuation_done;
					} else {
						if (op->function(op, revents))
						{
							op->status = pt_continuation_done;
						}
					}
				} else if ((rv == 0) ||
						((errno == EINTR) || (errno == EAGAIN))) {
					if (rv == 0)	/* poll timed out */
					{
						if (wait_for_remaining)
							now += remaining;
						else
							now += PR_MillisecondsToInterval(msecs);
					}
					else
						now = PR_IntervalNow();
					elapsed = (PRIntervalTime) (now - epoch);
					if (elapsed >= op->timeout) {
						op->result.code = -1;
						op->syserrno = ETIMEDOUT;
						op->status = pt_continuation_done;
					} else
						remaining = op->timeout - elapsed;
				} else {
					op->result.code = -1;
					op->syserrno = errno;
					op->status = pt_continuation_done;
				}
			} while (pt_continuation_done != op->status);
            break;
    }

}  /* pt_poll_now */

static PRIntn pt_Continue(pt_Continuation *op)
{
    op->status = pt_continuation_pending;  /* set default value */
	/*
	 * let each thread call poll directly
	 */
	pt_poll_now(op);
	PR_ASSERT(pt_continuation_done == op->status);
    return op->result.code;
}  /* pt_Continue */

/*****************************************************************************/
/*********************** specific continuation functions *********************/
/*****************************************************************************/
static PRBool pt_connect_cont(pt_Continuation *op, PRInt16 revents)
{
    op->syserrno = _MD_unix_get_nonblocking_connect_error(op->arg1.osfd);
    if (op->syserrno != 0) {
        op->result.code = -1;
    } else {
        op->result.code = 0;
    }
    return PR_TRUE; /* this one is cooked */
}  /* pt_connect_cont */

static PRBool pt_accept_cont(pt_Continuation *op, PRInt16 revents)
{
    op->syserrno = 0;
    op->result.code = accept(
        op->arg1.osfd, op->arg2.buffer, op->arg3.addr_len);
    if (-1 == op->result.code)
    {
        op->syserrno = errno;
        if (EWOULDBLOCK == errno || EAGAIN == errno || ECONNABORTED == errno)
            return PR_FALSE;  /* do nothing - this one ain't finished */
    }
    return PR_TRUE;
}  /* pt_accept_cont */

static PRBool pt_read_cont(pt_Continuation *op, PRInt16 revents)
{
    /*
     * Any number of bytes will complete the operation. It need
     * not (and probably will not) satisfy the request. The only
     * error we continue is EWOULDBLOCK|EAGAIN.
     */
    op->result.code = read(
        op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
    op->syserrno = errno;
    return ((-1 == op->result.code) && 
            (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?
        PR_FALSE : PR_TRUE;
}  /* pt_read_cont */

static PRBool pt_recv_cont(pt_Continuation *op, PRInt16 revents)
{
    /*
     * Any number of bytes will complete the operation. It need
     * not (and probably will not) satisfy the request. The only
     * error we continue is EWOULDBLOCK|EAGAIN.
     */
#if defined(SOLARIS)
    if (0 == op->arg4.flags)
        op->result.code = read(
            op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
    else
        op->result.code = recv(
            op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
#else
    op->result.code = recv(
        op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
#endif
    op->syserrno = errno;
    return ((-1 == op->result.code) && 
            (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?
        PR_FALSE : PR_TRUE;
}  /* pt_recv_cont */

static PRBool pt_send_cont(pt_Continuation *op, PRInt16 revents)
{
    PRIntn bytes;
#if defined(SOLARIS)
    PRInt32 tmp_amount = op->arg3.amount;
#endif
    /*
     * We want to write the entire amount out, no matter how many
     * tries it takes. Keep advancing the buffer and the decrementing
     * the amount until the amount goes away. Return the total bytes
     * (which should be the original amount) when finished (or an
     * error).
     */
#if defined(SOLARIS)
retry:
    bytes = write(op->arg1.osfd, op->arg2.buffer, tmp_amount);
#else
    bytes = send(
        op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
#endif
    op->syserrno = errno;

#if defined(SOLARIS)
    /*
     * The write system call has been reported to return the ERANGE error
     * on occasion. Try to write in smaller chunks to workaround this bug.
     */
    if ((bytes == -1) && (op->syserrno == ERANGE))
    {
        if (tmp_amount > 1)
        {
            tmp_amount = tmp_amount/2;  /* half the bytes */
            goto retry;
        }
    }
#endif

    if (bytes >= 0)  /* this is progress */
    {
        char *bp = (char*)op->arg2.buffer;
        bp += bytes;  /* adjust the buffer pointer */
        op->arg2.buffer = bp;
        op->result.code += bytes;  /* accumulate the number sent */
        op->arg3.amount -= bytes;  /* and reduce the required count */
        return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
    }
    else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
    {
        op->result.code = -1;
        return PR_TRUE;
    }
    else return PR_FALSE;
}  /* pt_send_cont */

static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents)
{
    PRIntn bytes;
    /*
     * We want to write the entire amount out, no matter how many
     * tries it takes. Keep advancing the buffer and the decrementing
     * the amount until the amount goes away. Return the total bytes
     * (which should be the original amount) when finished (or an
     * error).
     */
    bytes = write(op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
    op->syserrno = errno;
    if (bytes >= 0)  /* this is progress */
    {
        char *bp = (char*)op->arg2.buffer;
        bp += bytes;  /* adjust the buffer pointer */
        op->arg2.buffer = bp;
        op->result.code += bytes;  /* accumulate the number sent */
        op->arg3.amount -= bytes;  /* and reduce the required count */
        return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
    }
    else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
    {
        op->result.code = -1;
        return PR_TRUE;
    }
    else return PR_FALSE;
}  /* pt_write_cont */

static PRBool pt_writev_cont(pt_Continuation *op, PRInt16 revents)
{
    PRIntn bytes;
    struct iovec *iov = (struct iovec*)op->arg2.buffer;
    /*
     * Same rules as write, but continuing seems to be a bit more
     * complicated. As the number of bytes sent grows, we have to
     * redefine the vector we're pointing at. We might have to
     * modify an individual vector parms or we might have to eliminate
     * a pair altogether.
     */
    bytes = writev(op->arg1.osfd, iov, op->arg3.amount);
    op->syserrno = errno;
    if (bytes >= 0)  /* this is progress */
    {
        PRIntn iov_index;
        op->result.code += bytes;  /* accumulate the number sent */
        for (iov_index = 0; iov_index < op->arg3.amount; ++iov_index)
        {
            /* how much progress did we make in the i/o vector? */
            if (bytes < iov[iov_index].iov_len)
            {
                /* this element's not done yet */
                char **bp = (char**)&(iov[iov_index].iov_base);
                iov[iov_index].iov_len -= bytes;  /* there's that much left */
                *bp += bytes;  /* starting there */
                break;  /* go off and do that */
            }
            bytes -= iov[iov_index].iov_len;  /* that element's consumed */
        }
        op->arg2.buffer = &iov[iov_index];  /* new start of array */
        op->arg3.amount -= iov_index;  /* and array length */
        return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
    }
    else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
    {
        op->result.code = -1;
        return PR_TRUE;
    }
    else return PR_FALSE;
}  /* pt_writev_cont */

static PRBool pt_sendto_cont(pt_Continuation *op, PRInt16 revents)
{
    PRIntn bytes = sendto(
        op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags,
        (struct sockaddr*)op->arg5.addr, PR_NETADDR_SIZE(op->arg5.addr));
    op->syserrno = errno;
    if (bytes >= 0)  /* this is progress */
    {
        char *bp = (char*)op->arg2.buffer;
        bp += bytes;  /* adjust the buffer pointer */
        op->arg2.buffer = bp;
        op->result.code += bytes;  /* accumulate the number sent */
        op->arg3.amount -= bytes;  /* and reduce the required count */
        return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
    }
    else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
    {
        op->result.code = -1;
        return PR_TRUE;
    }
    else return PR_FALSE;
}  /* pt_sendto_cont */

static PRBool pt_recvfrom_cont(pt_Continuation *op, PRInt16 revents)
{
    pt_SockLen addr_len = sizeof(PRNetAddr);
    op->result.code = recvfrom(
        op->arg1.osfd, op->arg2.buffer, op->arg3.amount,
        op->arg4.flags, (struct sockaddr*)op->arg5.addr, &addr_len);
    op->syserrno = errno;
    return ((-1 == op->result.code) && 
            (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?
        PR_FALSE : PR_TRUE;
}  /* pt_recvfrom_cont */

#ifdef AIX
static PRBool pt_aix_sendfile_cont(pt_Continuation *op, PRInt16 revents)
{
    struct sf_parms *sf_struct = (struct sf_parms *) op->arg2.buffer;
    ssize_t rv;
	unsigned long long saved_file_offset;
	long long saved_file_bytes;

	saved_file_offset = sf_struct->file_offset;
	saved_file_bytes = sf_struct->file_bytes;
	sf_struct->bytes_sent = 0;

	if ((sf_struct->file_bytes > 0) && (sf_struct->file_size > 0))
	PR_ASSERT((sf_struct->file_bytes + sf_struct->file_offset) <=
									sf_struct->file_size);
    rv = AIX_SEND_FILE(&op->arg1.osfd, sf_struct, op->arg4.flags);
    op->syserrno = errno;

    if (rv != -1) {
        op->result.code += sf_struct->bytes_sent;
		/*
		 * A bug in AIX 4.3.2 prevents the 'file_bytes' field from
		 * being updated. So, 'file_bytes' is maintained by NSPR to
		 * avoid conflict when this bug is fixed in AIX, in the future.
		 */
		if (saved_file_bytes != -1)
			saved_file_bytes -= (sf_struct->file_offset - saved_file_offset);
		sf_struct->file_bytes = saved_file_bytes;
    } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
        op->result.code = -1;
    } else {
        return PR_FALSE;
    }

    if (rv == 1) {    /* more data to send */
        return PR_FALSE;
    }

    return PR_TRUE;
}
#endif  /* AIX */

#ifdef HPUX11
static PRBool pt_hpux_sendfile_cont(pt_Continuation *op, PRInt16 revents)
{
    struct iovec *hdtrl = (struct iovec *) op->arg2.buffer;
    int count;

    count = sendfile(op->arg1.osfd, op->filedesc, op->arg3.file_spec.offset,
			op->arg3.file_spec.nbytes, hdtrl, op->arg4.flags);
    PR_ASSERT(count <= op->nbytes_to_send);
    op->syserrno = errno;

    if (count != -1) {
        op->result.code += count;
    } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
        op->result.code = -1;
    } else {
        return PR_FALSE;
    }
    if (count != -1 && count < op->nbytes_to_send) {
        if (count < hdtrl[0].iov_len) {
			/* header not sent */

            hdtrl[0].iov_base = ((char *) hdtrl[0].iov_base) + count;
            hdtrl[0].iov_len -= count;

        } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes)) {
			/* header sent, file not sent */
            PRUint32 file_nbytes_sent = count - hdtrl[0].iov_len;

            hdtrl[0].iov_base = NULL;
            hdtrl[0].iov_len = 0;

            op->arg3.file_spec.offset += file_nbytes_sent;
            op->arg3.file_spec.nbytes -= file_nbytes_sent;
        } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes +
											hdtrl[1].iov_len)) {
            PRUint32 trailer_nbytes_sent = count - (hdtrl[0].iov_len +
                                         op->arg3.file_spec.nbytes);

			/* header sent, file sent, trailer not sent */

            hdtrl[0].iov_base = NULL;
            hdtrl[0].iov_len = 0;
			/*
			 * set file offset and len so that no more file data is
			 * sent
			 */
            op->arg3.file_spec.offset = op->arg3.file_spec.st_size;
            op->arg3.file_spec.nbytes = 0;

            hdtrl[1].iov_base =((char *) hdtrl[1].iov_base)+ trailer_nbytes_sent;
            hdtrl[1].iov_len -= trailer_nbytes_sent;
		}
        op->nbytes_to_send -= count;
        return PR_FALSE;
    }

    return PR_TRUE;
}
#endif  /* HPUX11 */

#ifdef SOLARIS  
static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents)
{
    struct sendfilevec *vec = (struct sendfilevec *) op->arg2.buffer;
    size_t xferred;
    ssize_t count;

    count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred);
    op->syserrno = errno;
    PR_ASSERT((count == -1) || (count == xferred));

    if (count == -1) {
        if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN
                && op->syserrno != EINTR) {
            op->result.code = -1;
            return PR_TRUE;
        }
        count = xferred;
    } else if (count == 0) {
        /* 
         * We are now at EOF. The file was truncated. Solaris sendfile is
         * supposed to return 0 and no error in this case, though some versions
         * may return -1 and EINVAL .
         */
        op->result.code = -1;
        op->syserrno = 0; /* will be treated as EOF */
        return PR_TRUE;
    }
    PR_ASSERT(count <= op->nbytes_to_send);
    
    op->result.code += count;
    if (count < op->nbytes_to_send) {
        op->nbytes_to_send -= count;

        while (count >= vec->sfv_len) {
            count -= vec->sfv_len;
            vec++;
            op->arg3.amount--;
        }
        PR_ASSERT(op->arg3.amount > 0);

        vec->sfv_off += count;
        vec->sfv_len -= count;
        PR_ASSERT(vec->sfv_len > 0);
        op->arg2.buffer = vec;

        return PR_FALSE;
    }

    return PR_TRUE;
}
#endif  /* SOLARIS */

#ifdef LINUX 
static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents)
{
    ssize_t rv;
    off_t oldoffset;

    oldoffset = op->offset;
    rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count);
    op->syserrno = errno;

    if (rv == -1) {
        if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
            op->result.code = -1;
            return PR_TRUE;
        }
        rv = 0;
    }
    PR_ASSERT(rv == op->offset - oldoffset);
    op->result.code += rv;
    if (rv < op->count) {
        op->count -= rv;
        return PR_FALSE;
    }
    return PR_TRUE;
}
#endif  /* LINUX */

void _PR_InitIO(void)
{
#if defined(DEBUG)
    memset(&pt_debug, 0, sizeof(PTDebug));
    pt_debug.timeStarted = PR_Now();
#endif

    _pr_flock_lock = PR_NewLock();
    PR_ASSERT(NULL != _pr_flock_lock);
    _pr_flock_cv = PR_NewCondVar(_pr_flock_lock);
    PR_ASSERT(NULL != _pr_flock_cv);
    _pr_rename_lock = PR_NewLock();
    PR_ASSERT(NULL != _pr_rename_lock); 

    _PR_InitFdCache();  /* do that */   

    _pr_stdin = pt_SetMethods(0, PR_DESC_FILE, PR_FALSE, PR_TRUE);
    _pr_stdout = pt_SetMethods(1, PR_DESC_FILE, PR_FALSE, PR_TRUE);
    _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE, PR_TRUE);
    PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr);

#ifdef _PR_IPV6_V6ONLY_PROBE
    /* In Mac OS X v10.3 Panther Beta the IPV6_V6ONLY socket option
     * is turned on by default, contrary to what RFC 3493, Section
     * 5.3 says.  So we have to turn it off.  Find out whether we
     * are running on such a system.
     */
    {
        int osfd;
        osfd = socket(AF_INET6, SOCK_STREAM, 0);
        if (osfd != -1) {
            int on;
            int optlen = sizeof(on);
            if (getsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY,
                    &on, &optlen) == 0) {
                _pr_ipv6_v6only_on_by_default = on;
            }
            close(osfd);
        }
    }
#endif
}  /* _PR_InitIO */

void _PR_CleanupIO(void)
{
    _PR_Putfd(_pr_stdin);
    _pr_stdin = NULL;
    _PR_Putfd(_pr_stdout);
    _pr_stdout = NULL;
    _PR_Putfd(_pr_stderr); 
    _pr_stderr = NULL;

    _PR_CleanupFdCache();
    
    if (_pr_flock_cv)
    {
        PR_DestroyCondVar(_pr_flock_cv);
        _pr_flock_cv = NULL;
    }
    if (_pr_flock_lock)
    {
        PR_DestroyLock(_pr_flock_lock);
        _pr_flock_lock = NULL;
    }
    if (_pr_rename_lock)
    {
        PR_DestroyLock(_pr_rename_lock);
        _pr_rename_lock = NULL;
    }
}  /* _PR_CleanupIO */

PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)
{
    PRFileDesc *result = NULL;
    PR_ASSERT(osfd >= PR_StandardInput && osfd <= PR_StandardError);

    if (!_pr_initialized) _PR_ImplicitInitialization();
    
    switch (osfd)
    {
        case PR_StandardInput: result = _pr_stdin; break;
        case PR_StandardOutput: result = _pr_stdout; break;
        case PR_StandardError: result = _pr_stderr; break;
        default:
            (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    }
    return result;
}  /* PR_GetSpecialFD */

/*****************************************************************************/
/***************************** I/O private methods ***************************/
/*****************************************************************************/

static PRBool pt_TestAbort(void)
{
    PRThread *me = PR_GetCurrentThread();
    if(_PT_THREAD_INTERRUPTED(me))
    {
        PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        me->state &= ~PT_THREAD_ABORTED;
        return PR_TRUE;
    }
    return PR_FALSE;
}  /* pt_TestAbort */

static void pt_MapError(void (*mapper)(PRIntn), PRIntn syserrno)
{
    switch (syserrno)
    {
        case EINTR:
            PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); break;
        case ETIMEDOUT:
            PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break;
        default:
            mapper(syserrno);
    }
}  /* pt_MapError */

static PRStatus pt_Close(PRFileDesc *fd)
{
    if ((NULL == fd) || (NULL == fd->secret)
        || ((_PR_FILEDESC_OPEN != fd->secret->state)
        && (_PR_FILEDESC_CLOSED != fd->secret->state)))
    {
        PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
        return PR_FAILURE;
    }
    if (pt_TestAbort()) return PR_FAILURE;

    if (_PR_FILEDESC_OPEN == fd->secret->state)
    {
        if (-1 == close(fd->secret->md.osfd))
        {
#ifdef OSF1
            /*
             * Bug 86941: On Tru64 UNIX V5.0A and V5.1, the close()
             * system call, when called to close a TCP socket, may
             * return -1 with errno set to EINVAL but the system call
             * does close the socket successfully.  An application
             * may safely ignore the EINVAL error.  This bug is fixed
             * on Tru64 UNIX V5.1A and later.  The defect tracking
             * number is QAR 81431.
             */
            if (PR_DESC_SOCKET_TCP != fd->methods->file_type
            || EINVAL != errno)
            {
                pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno);
                return PR_FAILURE;
            }
#else
            pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno);
            return PR_FAILURE;
#endif
        }
        fd->secret->state = _PR_FILEDESC_CLOSED;
    }
    _PR_Putfd(fd);
    return PR_SUCCESS;
}  /* pt_Close */

static PRInt32 pt_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
{
    PRInt32 syserrno, bytes = -1;

    if (pt_TestAbort()) return bytes;

    bytes = read(fd->secret->md.osfd, buf, amount);
    syserrno = errno;

    if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
        && (!fd->secret->nonblocking))
    {
        pt_Continuation op;
        op.arg1.osfd = fd->secret->md.osfd;
        op.arg2.buffer = buf;
        op.arg3.amount = amount;
        op.timeout = PR_INTERVAL_NO_TIMEOUT;
        op.function = pt_read_cont;
        op.event = POLLIN | POLLPRI;
        bytes = pt_Continue(&op);
        syserrno = op.syserrno;
    }
    if (bytes < 0)
        pt_MapError(_PR_MD_MAP_READ_ERROR, syserrno);
    return bytes;
}  /* pt_Read */

static PRInt32 pt_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
{
    PRInt32 syserrno, bytes = -1;
    PRBool fNeedContinue = PR_FALSE;

    if (pt_TestAbort()) return bytes;

    bytes = write(fd->secret->md.osfd, buf, amount);
    syserrno = errno;

    if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) )
    {
        buf = (char *) buf + bytes;
        amount -= bytes;
        fNeedContinue = PR_TRUE;
    }
    if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
        && (!fd->secret->nonblocking) )
    {
        bytes = 0;
        fNeedContinue = PR_TRUE;
    }

    if (fNeedContinue == PR_TRUE)
    {
        pt_Continuation op;
        op.arg1.osfd = fd->secret->md.osfd;
        op.arg2.buffer = (void*)buf;
        op.arg3.amount = amount;
        op.timeout = PR_INTERVAL_NO_TIMEOUT;
        op.result.code = bytes;  /* initialize the number sent */
        op.function = pt_write_cont;
        op.event = POLLOUT | POLLPRI;
        bytes = pt_Continue(&op);
        syserrno = op.syserrno;
    }
    if (bytes == -1)
        pt_MapError(_PR_MD_MAP_WRITE_ERROR, syserrno);
    return bytes;
}  /* pt_Write */

static PRInt32 pt_Writev(
    PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_len, PRIntervalTime timeout)
{
    PRIntn iov_index;
    PRBool fNeedContinue = PR_FALSE;
    PRInt32 syserrno, bytes, rv = -1;
    struct iovec osiov_local[PR_MAX_IOVECTOR_SIZE], *osiov;
    int osiov_len;

    if (pt_TestAbort()) return rv;

    /* Ensured by PR_Writev */
    PR_ASSERT(iov_len <= PR_MAX_IOVECTOR_SIZE);

    /*
     * We can't pass iov to writev because PRIOVec and struct iovec
     * may not be binary compatible.  Make osiov a copy of iov and
     * pass osiov to writev.  We can modify osiov if we need to
     * continue the operation.
     */
    osiov = osiov_local;
    osiov_len = iov_len;
    for (iov_index = 0; iov_index < osiov_len; iov_index++)
    {
        osiov[iov_index].iov_base = iov[iov_index].iov_base;
        osiov[iov_index].iov_len = iov[iov_index].iov_len;
    }

    rv = bytes = writev(fd->secret->md.osfd, osiov, osiov_len);
    syserrno = errno;

    if (!fd->secret->nonblocking)
    {
        if (bytes >= 0)
        {
            /*
             * If we moved some bytes, how does that implicate the
             * i/o vector list?  In other words, exactly where are
             * we within that array?  What are the parameters for
             * resumption?  Maybe we're done!
             */
            for ( ;osiov_len > 0; osiov++, osiov_len--)
            {
                if (bytes < osiov->iov_len)
                {
                    /* this one's not done yet */
                    osiov->iov_base = (char*)osiov->iov_base + bytes;
                    osiov->iov_len -= bytes;
                    break;  /* go off and do that */
                }
                bytes -= osiov->iov_len;  /* this one's done cooked */
            }
            PR_ASSERT(osiov_len > 0 || bytes == 0);
            if (osiov_len > 0)
            {
                if (PR_INTERVAL_NO_WAIT == timeout)
                {
                    rv = -1;
                    syserrno = ETIMEDOUT;
                }
                else fNeedContinue = PR_TRUE;
            }
        }
        else if (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
        {
            if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
            else
            {
                rv = 0;
                fNeedContinue = PR_TRUE;
            }
        }
    }

    if (fNeedContinue == PR_TRUE)
    {
        pt_Continuation op;

        op.arg1.osfd = fd->secret->md.osfd;
        op.arg2.buffer = (void*)osiov;
        op.arg3.amount = osiov_len;
        op.timeout = timeout;
        op.result.code = rv;
        op.function = pt_writev_cont;
        op.event = POLLOUT | POLLPRI;
        rv = pt_Continue(&op);
        syserrno = op.syserrno;
    }
    if (rv == -1) pt_MapError(_PR_MD_MAP_WRITEV_ERROR, syserrno);
    return rv;
}  /* pt_Writev */

static PRInt32 pt_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
{
    return _PR_MD_LSEEK(fd, offset, whence);
}  /* pt_Seek */

static PRInt64 pt_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
{
    return _PR_MD_LSEEK64(fd, offset, whence);
}  /* pt_Seek64 */

static PRInt32 pt_Available_f(PRFileDesc *fd)
{
    PRInt32 result, cur, end;

    cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR);

    if (cur >= 0)
        end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END);

    if ((cur < 0) || (end < 0)) {
        return -1;
    }

    result = end - cur;
    _PR_MD_LSEEK(fd, cur, PR_SEEK_SET);

    return result;
}  /* pt_Available_f */

static PRInt64 pt_Available64_f(PRFileDesc *fd)
{
    PRInt64 result, cur, end;
    PRInt64 minus_one;

    LL_I2L(minus_one, -1);
    cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR);

    if (LL_GE_ZERO(cur))
        end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END);

    if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one;

    LL_SUB(result, end, cur);
    (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET);

    return result;
}  /* pt_Available64_f */

static PRInt32 pt_Available_s(PRFileDesc *fd)
{
    PRInt32 rv, bytes = -1;
    if (pt_TestAbort()) return bytes;

    rv = ioctl(fd->secret->md.osfd, FIONREAD, &bytes);

    if (rv == -1)
        pt_MapError(_PR_MD_MAP_SOCKETAVAILABLE_ERROR, errno);
    return bytes;
}  /* pt_Available_s */

static PRInt64 pt_Available64_s(PRFileDesc *fd)
{
    PRInt64 rv;
    LL_I2L(rv, pt_Available_s(fd));
    return rv;
}  /* pt_Available64_s */

static PRStatus pt_FileInfo(PRFileDesc *fd, PRFileInfo *info)
{
    PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, info);
    return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
}  /* pt_FileInfo */

static PRStatus pt_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
{
    PRInt32 rv = _PR_MD_GETOPENFILEINFO64(fd, info);
    return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
}  /* pt_FileInfo64 */

static PRStatus pt_Synch(PRFileDesc *fd)
{
    return (NULL == fd) ? PR_FAILURE : PR_SUCCESS;
} /* pt_Synch */

static PRStatus pt_Fsync(PRFileDesc *fd)
{
    PRIntn rv = -1;
    if (pt_TestAbort()) return PR_FAILURE;

    rv = fsync(fd->secret->md.osfd);
    if (rv < 0) {
        pt_MapError(_PR_MD_MAP_FSYNC_ERROR, errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}  /* pt_Fsync */

static PRStatus pt_Connect(
    PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
{
    PRIntn rv = -1, syserrno;
    pt_SockLen addr_len;
	const PRNetAddr *addrp = addr;
#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
	PRUint16 md_af = addr->raw.family;
    PRNetAddr addrCopy;
#endif

    if (pt_TestAbort()) return PR_FAILURE;

    PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
    addr_len = PR_NETADDR_SIZE(addr);
#if defined(_PR_INET6)
	if (addr->raw.family == PR_AF_INET6) {
		md_af = AF_INET6;
#ifndef _PR_HAVE_SOCKADDR_LEN
		addrCopy = *addr;
		addrCopy.raw.family = AF_INET6;
		addrp = &addrCopy;
#endif
	}
#endif

#ifdef _PR_HAVE_SOCKADDR_LEN
    addrCopy = *addr;
    ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
    ((struct sockaddr*)&addrCopy)->sa_family = md_af;
    addrp = &addrCopy;
#endif
    rv = connect(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);
    syserrno = errno;
    if ((-1 == rv) && (EINPROGRESS == syserrno) && (!fd->secret->nonblocking))
    {
        if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
        else
        {
            pt_Continuation op;
            op.arg1.osfd = fd->secret->md.osfd;
            op.arg2.buffer = (void*)addrp;
            op.arg3.amount = addr_len;
            op.timeout = timeout;
            op.function = pt_connect_cont;
            op.event = POLLOUT | POLLPRI;
            rv = pt_Continue(&op);
            syserrno = op.syserrno;
        }
    }
    if (-1 == rv) {
        pt_MapError(_PR_MD_MAP_CONNECT_ERROR, syserrno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}  /* pt_Connect */

static PRStatus pt_ConnectContinue(
    PRFileDesc *fd, PRInt16 out_flags)
{
    int err;
    PRInt32 osfd;

    if (out_flags & PR_POLL_NVAL)
    {
        PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
        return PR_FAILURE;
    }
    if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0)
    {
        PR_ASSERT(out_flags == 0);
        PR_SetError(PR_IN_PROGRESS_ERROR, 0);
        return PR_FAILURE;
    }

    osfd = fd->secret->md.osfd;

    err = _MD_unix_get_nonblocking_connect_error(osfd);
    if (err != 0)
    {
        _PR_MD_MAP_CONNECT_ERROR(err);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}  /* pt_ConnectContinue */

PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
{
    /* Find the NSPR layer and invoke its connectcontinue method */
    PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);

    if (NULL == bottom)
    {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        return PR_FAILURE;
    }
    return pt_ConnectContinue(bottom, pd->out_flags);
}  /* PR_GetConnectStatus */

static PRFileDesc* pt_Accept(
    PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
{
    PRFileDesc *newfd = NULL;
    PRIntn syserrno, osfd = -1;
    pt_SockLen addr_len = sizeof(PRNetAddr);
#ifdef SYMBIAN
    PRNetAddr dummy_addr;
#endif

    if (pt_TestAbort()) return newfd;

#ifdef SYMBIAN
    /* On Symbian OS, accept crashes if addr is NULL. */
    if (!addr)
        addr = &dummy_addr;
#endif

#ifdef _PR_STRICT_ADDR_LEN
    if (addr)
    {
        /*
         * Set addr->raw.family just so that we can use the
         * PR_NETADDR_SIZE macro.
         */
        addr->raw.family = fd->secret->af;
        addr_len = PR_NETADDR_SIZE(addr);
    }
#endif

    osfd = accept(fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
    syserrno = errno;

    if (osfd == -1)
    {
        if (fd->secret->nonblocking) goto failed;

        if (EWOULDBLOCK != syserrno && EAGAIN != syserrno
        && ECONNABORTED != syserrno)
            goto failed;
        else
        {
            if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
            else
            {
                pt_Continuation op;
                op.arg1.osfd = fd->secret->md.osfd;
                op.arg2.buffer = addr;
                op.arg3.addr_len = &addr_len;
                op.timeout = timeout;
                op.function = pt_accept_cont;
                op.event = POLLIN | POLLPRI;
                osfd = pt_Continue(&op);
                syserrno = op.syserrno;
            }
            if (osfd < 0) goto failed;
        }
    }
#ifdef _PR_HAVE_SOCKADDR_LEN
    /* ignore the sa_len field of struct sockaddr */
    if (addr)
    {
        addr->raw.family = ((struct sockaddr*)addr)->sa_family;
    }
#endif /* _PR_HAVE_SOCKADDR_LEN */
#ifdef _PR_INET6
	if (addr && (AF_INET6 == addr->raw.family))
        addr->raw.family = PR_AF_INET6;
#endif
    newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE, PR_FALSE);
    if (newfd == NULL) close(osfd);  /* $$$ whoops! this doesn't work $$$ */
    else
    {
        PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
        PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
#ifdef LINUX
        /*
         * On Linux, experiments showed that the accepted sockets
         * inherit the TCP_NODELAY socket option of the listening
         * socket.
         */
        newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay;
#endif
    }
    return newfd;

failed:
    pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno);
    return NULL;
}  /* pt_Accept */

static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr)
{
    PRIntn rv;
    pt_SockLen addr_len;
	const PRNetAddr *addrp = addr;
#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
	PRUint16 md_af = addr->raw.family;
    PRNetAddr addrCopy;
#endif

    if (pt_TestAbort()) return PR_FAILURE;

    PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
    if (addr->raw.family == AF_UNIX)
    {
        /* Disallow relative pathnames */
        if (addr->local.path[0] != '/')
        {
            PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
            return PR_FAILURE;
        }
    }

#if defined(_PR_INET6)
	if (addr->raw.family == PR_AF_INET6) {
		md_af = AF_INET6;
#ifndef _PR_HAVE_SOCKADDR_LEN
		addrCopy = *addr;
		addrCopy.raw.family = AF_INET6;
		addrp = &addrCopy;
#endif
	}
#endif

    addr_len = PR_NETADDR_SIZE(addr);
#ifdef _PR_HAVE_SOCKADDR_LEN
    addrCopy = *addr;
    ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
    ((struct sockaddr*)&addrCopy)->sa_family = md_af;
    addrp = &addrCopy;
#endif
    rv = bind(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);

    if (rv == -1) {
        pt_MapError(_PR_MD_MAP_BIND_ERROR, errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}  /* pt_Bind */

static PRStatus pt_Listen(PRFileDesc *fd, PRIntn backlog)
{
    PRIntn rv;

    if (pt_TestAbort()) return PR_FAILURE;

    rv = listen(fd->secret->md.osfd, backlog);
    if (rv == -1) {
        pt_MapError(_PR_MD_MAP_LISTEN_ERROR, errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}  /* pt_Listen */

static PRStatus pt_Shutdown(PRFileDesc *fd, PRIntn how)
{
    PRIntn rv = -1;
    if (pt_TestAbort()) return PR_FAILURE;

    rv = shutdown(fd->secret->md.osfd, how);

    if (rv == -1) {
        pt_MapError(_PR_MD_MAP_SHUTDOWN_ERROR, errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}  /* pt_Shutdown */

static PRInt16 pt_Poll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
{
    *out_flags = 0;
    return in_flags;
}  /* pt_Poll */

static PRInt32 pt_Recv(
    PRFileDesc *fd, void *buf, PRInt32 amount,
    PRIntn flags, PRIntervalTime timeout)
{
    PRInt32 syserrno, bytes = -1;
    PRIntn osflags;

    if (0 == flags)
        osflags = 0;
    else if (PR_MSG_PEEK == flags)
    {
#ifdef SYMBIAN
        /* MSG_PEEK doesn't work as expected. */
        PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
        return bytes;
#else
        osflags = MSG_PEEK;
#endif
    }
    else
    {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        return bytes;
    }

    if (pt_TestAbort()) return bytes;

    /* recv() is a much slower call on pre-2.6 Solaris than read(). */
#if defined(SOLARIS)
    if (0 == osflags)
        bytes = read(fd->secret->md.osfd, buf, amount);
    else
        bytes = recv(fd->secret->md.osfd, buf, amount, osflags);
#else
    bytes = recv(fd->secret->md.osfd, buf, amount, osflags);
#endif
    syserrno = errno;

    if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
        && (!fd->secret->nonblocking))
    {
        if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
        else
        {
            pt_Continuation op;
            op.arg1.osfd = fd->secret->md.osfd;
            op.arg2.buffer = buf;
            op.arg3.amount = amount;
            op.arg4.flags = osflags;
            op.timeout = timeout;
            op.function = pt_recv_cont;
            op.event = POLLIN | POLLPRI;
            bytes = pt_Continue(&op);
            syserrno = op.syserrno;
        }
    }
    if (bytes < 0)
        pt_MapError(_PR_MD_MAP_RECV_ERROR, syserrno);
    return bytes;
}  /* pt_Recv */

static PRInt32 pt_SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount)
{
    return pt_Recv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
}  /* pt_SocketRead */

static PRInt32 pt_Send(
    PRFileDesc *fd, const void *buf, PRInt32 amount,
    PRIntn flags, PRIntervalTime timeout)
{
    PRInt32 syserrno, bytes = -1;
    PRBool fNeedContinue = PR_FALSE;
#if defined(SOLARIS)
	PRInt32 tmp_amount = amount;
#endif

    /*
     * Under HP-UX DCE threads, pthread.h includes dce/cma_ux.h,
     * which has the following:
     *     #  define send        cma_send
     *     extern int  cma_send (int , void *, int, int );
     * So we need to cast away the 'const' of argument #2 for send().
     */
#if defined (HPUX) && defined(_PR_DCETHREADS)
#define PT_SENDBUF_CAST (void *)
#else
#define PT_SENDBUF_CAST
#endif

    if (pt_TestAbort()) return bytes;

    /*
     * On pre-2.6 Solaris, send() is much slower than write().
     * On 2.6 and beyond, with in-kernel sockets, send() and
     * write() are fairly equivalent in performance.
     */
#if defined(SOLARIS)
    PR_ASSERT(0 == flags);
retry:
    bytes = write(fd->secret->md.osfd, PT_SENDBUF_CAST buf, tmp_amount);
#else
    bytes = send(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount, flags);
#endif
    syserrno = errno;

#if defined(SOLARIS)
    /*
     * The write system call has been reported to return the ERANGE error
     * on occasion. Try to write in smaller chunks to workaround this bug.
     */
    if ((bytes == -1) && (syserrno == ERANGE))
    {
        if (tmp_amount > 1)
        {
            tmp_amount = tmp_amount/2;  /* half the bytes */
            goto retry;
        }
    }
#endif

    if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) )
    {
        if (PR_INTERVAL_NO_WAIT == timeout)
        {
            bytes = -1;
            syserrno = ETIMEDOUT;
        }
        else
        {
            buf = (char *) buf + bytes;
            amount -= bytes;
            fNeedContinue = PR_TRUE;
        }
    }
    if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
        && (!fd->secret->nonblocking) )
    {
        if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
        else
        {
            bytes = 0;
            fNeedContinue = PR_TRUE;
        }
    }

    if (fNeedContinue == PR_TRUE)
    {
        pt_Continuation op;
        op.arg1.osfd = fd->secret->md.osfd;
        op.arg2.buffer = (void*)buf;
        op.arg3.amount = amount;
        op.arg4.flags = flags;
        op.timeout = timeout;
        op.result.code = bytes;  /* initialize the number sent */
        op.function = pt_send_cont;
        op.event = POLLOUT | POLLPRI;
        bytes = pt_Continue(&op);
        syserrno = op.syserrno;
    }
    if (bytes == -1)
        pt_MapError(_PR_MD_MAP_SEND_ERROR, syserrno);
    return bytes;
}  /* pt_Send */

static PRInt32 pt_SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
{
    return pt_Send(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
}  /* pt_SocketWrite */

static PRInt32 pt_SendTo(
    PRFileDesc *fd, const void *buf,
    PRInt32 amount, PRIntn flags, const PRNetAddr *addr,
    PRIntervalTime timeout)
{
    PRInt32 syserrno, bytes = -1;
    PRBool fNeedContinue = PR_FALSE;
    pt_SockLen addr_len;
	const PRNetAddr *addrp = addr;
#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
	PRUint16 md_af = addr->raw.family;
    PRNetAddr addrCopy;
#endif

    if (pt_TestAbort()) return bytes;

    PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
#if defined(_PR_INET6)
	if (addr->raw.family == PR_AF_INET6) {
		md_af = AF_INET6;
#ifndef _PR_HAVE_SOCKADDR_LEN
		addrCopy = *addr;
		addrCopy.raw.family = AF_INET6;
		addrp = &addrCopy;
#endif
	}
#endif

    addr_len = PR_NETADDR_SIZE(addr);
#ifdef _PR_HAVE_SOCKADDR_LEN
    addrCopy = *addr;
    ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
    ((struct sockaddr*)&addrCopy)->sa_family = md_af;
    addrp = &addrCopy;
#endif
    bytes = sendto(
        fd->secret->md.osfd, buf, amount, flags,
        (struct sockaddr*)addrp, addr_len);
    syserrno = errno;
    if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
        && (!fd->secret->nonblocking) )
    {
        if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
        else fNeedContinue = PR_TRUE;
    }
    if (fNeedContinue == PR_TRUE)
    {
        pt_Continuation op;
        op.arg1.osfd = fd->secret->md.osfd;
        op.arg2.buffer = (void*)buf;
        op.arg3.amount = amount;
        op.arg4.flags = flags;
        op.arg5.addr = (PRNetAddr*)addrp;
        op.timeout = timeout;
        op.result.code = 0;  /* initialize the number sent */
        op.function = pt_sendto_cont;
        op.event = POLLOUT | POLLPRI;
        bytes = pt_Continue(&op);
        syserrno = op.syserrno;
    }
    if (bytes < 0)
        pt_MapError(_PR_MD_MAP_SENDTO_ERROR, syserrno);
    return bytes;
}  /* pt_SendTo */

static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
    PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
{
    PRBool fNeedContinue = PR_FALSE;
    PRInt32 syserrno, bytes = -1;
    pt_SockLen addr_len = sizeof(PRNetAddr);

    if (pt_TestAbort()) return bytes;

    bytes = recvfrom(
        fd->secret->md.osfd, buf, amount, flags,
        (struct sockaddr*)addr, &addr_len);
    syserrno = errno;

    if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
        && (!fd->secret->nonblocking) )
    {
        if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
        else fNeedContinue = PR_TRUE;
    }

    if (fNeedContinue == PR_TRUE)
    {
        pt_Continuation op;
        op.arg1.osfd = fd->secret->md.osfd;
        op.arg2.buffer = buf;
        op.arg3.amount = amount;
        op.arg4.flags = flags;
        op.arg5.addr = addr;
        op.timeout = timeout;
        op.function = pt_recvfrom_cont;
        op.event = POLLIN | POLLPRI;
        bytes = pt_Continue(&op);
        syserrno = op.syserrno;
    }
    if (bytes >= 0)
    {
#ifdef _PR_HAVE_SOCKADDR_LEN
        /* ignore the sa_len field of struct sockaddr */
        if (addr)
        {
            addr->raw.family = ((struct sockaddr*)addr)->sa_family;
        }
#endif /* _PR_HAVE_SOCKADDR_LEN */
#ifdef _PR_INET6
        if (addr && (AF_INET6 == addr->raw.family))
            addr->raw.family = PR_AF_INET6;
#endif
    }
    else
        pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno);
    return bytes;
}  /* pt_RecvFrom */

#ifdef AIX
#ifndef HAVE_SEND_FILE
static pthread_once_t pt_aix_sendfile_once_block = PTHREAD_ONCE_INIT;

static void pt_aix_sendfile_init_routine(void)
{
    void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
    pt_aix_sendfile_fptr = (ssize_t (*)()) dlsym(handle, "send_file");
    dlclose(handle);
}

/* 
 * pt_AIXDispatchSendFile
 */
static PRInt32 pt_AIXDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd,
	  PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    int rv;

    rv = pthread_once(&pt_aix_sendfile_once_block,
            pt_aix_sendfile_init_routine);
    PR_ASSERT(0 == rv);
    if (pt_aix_sendfile_fptr) {
        return pt_AIXSendFile(sd, sfd, flags, timeout);
    } else {
        return PR_EmulateSendFile(sd, sfd, flags, timeout);
    }
}
#endif /* !HAVE_SEND_FILE */


/*
 * pt_AIXSendFile
 *
 *    Send file sfd->fd across socket sd. If specified, header and trailer
 *    buffers are sent before and after the file, respectively. 
 *
 *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
 *    
 *    return number of bytes sent or -1 on error
 *
 *      This implementation takes advantage of the send_file() system
 *      call available in AIX 4.3.2.
 */

static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd, 
		PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    struct sf_parms sf_struct;
    uint_t send_flags;
    ssize_t rv;
    int syserrno;
    PRInt32 count;
	unsigned long long saved_file_offset;
	long long saved_file_bytes;

    sf_struct.header_data = (void *) sfd->header;  /* cast away the 'const' */
    sf_struct.header_length = sfd->hlen;
    sf_struct.file_descriptor = sfd->fd->secret->md.osfd;
    sf_struct.file_size = 0;
    sf_struct.file_offset = sfd->file_offset;
    if (sfd->file_nbytes == 0)
    	sf_struct.file_bytes = -1;
	else
    	sf_struct.file_bytes = sfd->file_nbytes;
    sf_struct.trailer_data = (void *) sfd->trailer;
    sf_struct.trailer_length = sfd->tlen;
    sf_struct.bytes_sent = 0;

	saved_file_offset = sf_struct.file_offset;
    saved_file_bytes = sf_struct.file_bytes;

    send_flags = 0;			/* flags processed at the end */

    /* The first argument to send_file() is int*. */
    PR_ASSERT(sizeof(int) == sizeof(sd->secret->md.osfd));
    do {
        rv = AIX_SEND_FILE(&sd->secret->md.osfd, &sf_struct, send_flags);
    } while (rv == -1 && (syserrno = errno) == EINTR);

    if (rv == -1) {
        if (syserrno == EAGAIN || syserrno == EWOULDBLOCK) {
            count = 0; /* Not a real error.  Need to continue. */
        } else {
            count = -1;
        }
    } else {
        count = sf_struct.bytes_sent;
		/*
		 * A bug in AIX 4.3.2 prevents the 'file_bytes' field from
		 * being updated. So, 'file_bytes' is maintained by NSPR to
		 * avoid conflict when this bug is fixed in AIX, in the future.
		 */
		if (saved_file_bytes != -1)
			saved_file_bytes -= (sf_struct.file_offset - saved_file_offset);
		sf_struct.file_bytes = saved_file_bytes;
    }

    if ((rv == 1) || ((rv == -1) && (count == 0))) {
        pt_Continuation op;

        op.arg1.osfd = sd->secret->md.osfd;
        op.arg2.buffer = &sf_struct;
        op.arg4.flags = send_flags;
        op.result.code = count;
        op.timeout = timeout;
        op.function = pt_aix_sendfile_cont;
        op.event = POLLOUT | POLLPRI;
        count = pt_Continue(&op);
        syserrno = op.syserrno;
    }

    if (count == -1) {
        pt_MapError(_MD_aix_map_sendfile_error, syserrno);
        return -1;
    }
    if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
        PR_Close(sd);
    }
	PR_ASSERT(count == (sfd->hlen + sfd->tlen +
						((sfd->file_nbytes ==  0) ?
						sf_struct.file_size - sfd->file_offset :
						sfd->file_nbytes)));
    return count;
}
#endif /* AIX */

#ifdef HPUX11
/*
 * pt_HPUXSendFile
 *
 *    Send file sfd->fd across socket sd. If specified, header and trailer
 *    buffers are sent before and after the file, respectively.
 *
 *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
 *    
 *    return number of bytes sent or -1 on error
 *
 *      This implementation takes advantage of the sendfile() system
 *      call available in HP-UX B.11.00.
 */

static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd, 
		PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    struct stat statbuf;
    size_t nbytes_to_send, file_nbytes_to_send;
    struct iovec hdtrl[2];  /* optional header and trailer buffers */
    int send_flags;
    PRInt32 count;
    int syserrno;

    if (sfd->file_nbytes == 0) {
        /* Get file size */
        if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
            _PR_MD_MAP_FSTAT_ERROR(errno);
            return -1;
        } 		
        file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
    } else {
        file_nbytes_to_send = sfd->file_nbytes;
    }
    nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send;

    hdtrl[0].iov_base = (void *) sfd->header;  /* cast away the 'const' */
    hdtrl[0].iov_len = sfd->hlen;
    hdtrl[1].iov_base = (void *) sfd->trailer;
    hdtrl[1].iov_len = sfd->tlen;
    /*
     * SF_DISCONNECT seems to close the socket even if sendfile()
     * only does a partial send on a nonblocking socket.  This
     * would prevent the subsequent sendfile() calls on that socket
     * from working.  So we don't use the SD_DISCONNECT flag.
     */
    send_flags = 0;

    do {
        count = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd,
                sfd->file_offset, file_nbytes_to_send, hdtrl, send_flags);
    } while (count == -1 && (syserrno = errno) == EINTR);

    if (count == -1 && (syserrno == EAGAIN || syserrno == EWOULDBLOCK)) {
        count = 0;
    }
    if (count != -1 && count < nbytes_to_send) {
        pt_Continuation op;

        if (count < sfd->hlen) {
			/* header not sent */

            hdtrl[0].iov_base = ((char *) sfd->header) + count;
            hdtrl[0].iov_len = sfd->hlen - count;
            op.arg3.file_spec.offset = sfd->file_offset;
            op.arg3.file_spec.nbytes = file_nbytes_to_send;
        } else if (count < (sfd->hlen + file_nbytes_to_send)) {
			/* header sent, file not sent */

            hdtrl[0].iov_base = NULL;
            hdtrl[0].iov_len = 0;

            op.arg3.file_spec.offset = sfd->file_offset + count - sfd->hlen;
            op.arg3.file_spec.nbytes = file_nbytes_to_send - (count - sfd->hlen);
        } else if (count < (sfd->hlen + file_nbytes_to_send + sfd->tlen)) {
			PRUint32 trailer_nbytes_sent;

			/* header sent, file sent, trailer not sent */

            hdtrl[0].iov_base = NULL;
            hdtrl[0].iov_len = 0;
			/*
			 * set file offset and len so that no more file data is
			 * sent
			 */
            op.arg3.file_spec.offset = statbuf.st_size;
            op.arg3.file_spec.nbytes = 0;

			trailer_nbytes_sent = count - sfd->hlen - file_nbytes_to_send;
            hdtrl[1].iov_base = ((char *) sfd->trailer) + trailer_nbytes_sent;
            hdtrl[1].iov_len = sfd->tlen - trailer_nbytes_sent;
		}

        op.arg1.osfd = sd->secret->md.osfd;
        op.filedesc = sfd->fd->secret->md.osfd;
        op.arg2.buffer = hdtrl;
        op.arg3.file_spec.st_size = statbuf.st_size;
        op.arg4.flags = send_flags;
        op.nbytes_to_send = nbytes_to_send - count;
        op.result.code = count;
        op.timeout = timeout;
        op.function = pt_hpux_sendfile_cont;
        op.event = POLLOUT | POLLPRI;
        count = pt_Continue(&op);
        syserrno = op.syserrno;
    }

    if (count == -1) {
        pt_MapError(_MD_hpux_map_sendfile_error, syserrno);
        return -1;
    }
    if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
        PR_Close(sd);
    }
    PR_ASSERT(count == nbytes_to_send);
    return count;
}

#endif  /* HPUX11 */

#ifdef SOLARIS 

/*
 *    pt_SolarisSendFile
 *
 *    Send file sfd->fd across socket sd. If specified, header and trailer
 *    buffers are sent before and after the file, respectively.
 *
 *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
 *
 *    return number of bytes sent or -1 on error
 *
 *    This implementation takes advantage of the sendfilev() system
 *    call available in Solaris 8.
 */

static PRInt32 pt_SolarisSendFile(PRFileDesc *sd, PRSendFileData *sfd,
                PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    struct stat statbuf;
    size_t nbytes_to_send, file_nbytes_to_send;	
    struct sendfilevec sfv_struct[3];  
    int sfvcnt = 0;	
    size_t xferred;
    PRInt32 count;
    int syserrno;

    if (sfd->file_nbytes == 0) {
        /* Get file size */
        if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
            _PR_MD_MAP_FSTAT_ERROR(errno);
            return -1;
        } 		
        file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
    } else {
        file_nbytes_to_send = sfd->file_nbytes;
    }

    nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send;

    if (sfd->hlen != 0) {
        sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF;
        sfv_struct[sfvcnt].sfv_flag = 0;
        sfv_struct[sfvcnt].sfv_off = (off_t) sfd->header; 
        sfv_struct[sfvcnt].sfv_len = sfd->hlen;
        sfvcnt++;
    }

    if (file_nbytes_to_send != 0) {
        sfv_struct[sfvcnt].sfv_fd = sfd->fd->secret->md.osfd;
        sfv_struct[sfvcnt].sfv_flag = 0;
        sfv_struct[sfvcnt].sfv_off = sfd->file_offset;
        sfv_struct[sfvcnt].sfv_len = file_nbytes_to_send;
        sfvcnt++;
    }

    if (sfd->tlen != 0) {
        sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF;
        sfv_struct[sfvcnt].sfv_flag = 0;
        sfv_struct[sfvcnt].sfv_off = (off_t) sfd->trailer; 
        sfv_struct[sfvcnt].sfv_len = sfd->tlen;
        sfvcnt++;
    }

    if (0 == sfvcnt) {
        count = 0;
        goto done;
    }
   	   
    /*
     * Strictly speaking, we may have sent some bytes when the
     * sendfilev() is interrupted and we should retry it from an
     * updated offset.  We are not doing that here.
     */
    count = SOLARIS_SENDFILEV(sd->secret->md.osfd, sfv_struct,
            sfvcnt, &xferred);

    PR_ASSERT((count == -1) || (count == xferred));

    if (count == -1) {
        syserrno = errno;
        if (syserrno == EINTR
                || syserrno == EAGAIN || syserrno == EWOULDBLOCK) {
            count = xferred;
        }
    } else if (count == 0) {
        /*
         * We are now at EOF. The file was truncated. Solaris sendfile is
         * supposed to return 0 and no error in this case, though some versions
         * may return -1 and EINVAL .
         */
        count = -1;
        syserrno = 0;  /* will be treated as EOF */
    }

    if (count != -1 && count < nbytes_to_send) {
        pt_Continuation op;
        struct sendfilevec *vec = sfv_struct;
        PRInt32 rem = count;

        while (rem >= vec->sfv_len) {
            rem -= vec->sfv_len;
            vec++;
            sfvcnt--;
        }
        PR_ASSERT(sfvcnt > 0);

        vec->sfv_off += rem;
        vec->sfv_len -= rem;
        PR_ASSERT(vec->sfv_len > 0);

        op.arg1.osfd = sd->secret->md.osfd;
        op.arg2.buffer = vec;
        op.arg3.amount = sfvcnt;
        op.arg4.flags = 0;
        op.nbytes_to_send = nbytes_to_send - count;
        op.result.code = count;
        op.timeout = timeout;
        op.function = pt_solaris_sendfile_cont;
        op.event = POLLOUT | POLLPRI;
        count = pt_Continue(&op);
        syserrno = op.syserrno;
    }

done:
    if (count == -1) {
        pt_MapError(_MD_solaris_map_sendfile_error, syserrno);
        return -1;
    }
    if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
        PR_Close(sd);
    }
    PR_ASSERT(count == nbytes_to_send);
    return count;
}

#ifndef HAVE_SENDFILEV
static pthread_once_t pt_solaris_sendfilev_once_block = PTHREAD_ONCE_INIT;

static void pt_solaris_sendfilev_init_routine(void)
{
    void *handle;
    PRBool close_it = PR_FALSE;
 
    /*
     * We do not want to unload libsendfile.so.  This handle is leaked
     * intentionally.
     */
    handle = dlopen("libsendfile.so", RTLD_LAZY | RTLD_GLOBAL);
    PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
        ("dlopen(libsendfile.so) returns %p", handle));

    if (NULL == handle) {
        /*
         * The dlopen(0, mode) call is to allow for the possibility that
         * sendfilev() may become part of a standard system library in a
         * future Solaris release.
         */
        handle = dlopen(0, RTLD_LAZY | RTLD_GLOBAL);
        PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
            ("dlopen(0) returns %p", handle));
        close_it = PR_TRUE;
    }
    pt_solaris_sendfilev_fptr = (ssize_t (*)()) dlsym(handle, "sendfilev");
    PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
        ("dlsym(sendfilev) returns %p", pt_solaris_sendfilev_fptr));
    
    if (close_it) {
        dlclose(handle);
    }
}

/* 
 * pt_SolarisDispatchSendFile
 */
static PRInt32 pt_SolarisDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd,
	  PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    int rv;

    rv = pthread_once(&pt_solaris_sendfilev_once_block,
            pt_solaris_sendfilev_init_routine);
    PR_ASSERT(0 == rv);
    if (pt_solaris_sendfilev_fptr) {
        return pt_SolarisSendFile(sd, sfd, flags, timeout);
    } else {
        return PR_EmulateSendFile(sd, sfd, flags, timeout);
    }
}
#endif /* !HAVE_SENDFILEV */

#endif  /* SOLARIS */

#ifdef LINUX
/*
 * pt_LinuxSendFile
 *
 *    Send file sfd->fd across socket sd. If specified, header and trailer
 *    buffers are sent before and after the file, respectively.
 *
 *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
 *    
 *    return number of bytes sent or -1 on error
 *
 *      This implementation takes advantage of the sendfile() system
 *      call available in Linux kernel 2.2 or higher.
 */

static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd,
                PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    struct stat statbuf;
    size_t file_nbytes_to_send;	
    PRInt32 count = 0;
    ssize_t rv;
    int syserrno;
    off_t offset;
    PRBool tcp_cork_enabled = PR_FALSE;
    int tcp_cork;

    if (sfd->file_nbytes == 0) {
        /* Get file size */
        if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
            _PR_MD_MAP_FSTAT_ERROR(errno);
            return -1;
        } 		
        file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
    } else {
        file_nbytes_to_send = sfd->file_nbytes;
    }

    if ((sfd->hlen != 0 || sfd->tlen != 0)
            && sd->secret->md.tcp_nodelay == 0) {
        tcp_cork = 1;
        if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
                &tcp_cork, sizeof tcp_cork) == 0) {
            tcp_cork_enabled = PR_TRUE;
        } else {
            syserrno = errno;
            if (syserrno != EINVAL) {
                _PR_MD_MAP_SETSOCKOPT_ERROR(syserrno);
                return -1;
            }
            /*
             * The most likely reason for the EINVAL error is that
             * TCP_NODELAY is set (with a function other than
             * PR_SetSocketOption).  This is not fatal, so we keep
             * on going.
             */
            PR_LOG(_pr_io_lm, PR_LOG_WARNING,
                ("pt_LinuxSendFile: "
                "setsockopt(TCP_CORK) failed with EINVAL\n"));
        }
    }

    if (sfd->hlen != 0) {
        count = PR_Send(sd, sfd->header, sfd->hlen, 0, timeout);
        if (count == -1) {
            goto failed;
        }
    }

    if (file_nbytes_to_send != 0) {
        offset = sfd->file_offset;
        do {
            rv = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd,
                &offset, file_nbytes_to_send);
        } while (rv == -1 && (syserrno = errno) == EINTR);
        if (rv == -1) {
            if (syserrno != EAGAIN && syserrno != EWOULDBLOCK) {
                _MD_linux_map_sendfile_error(syserrno);
                count = -1;
                goto failed;
            }
            rv = 0;
        }
        PR_ASSERT(rv == offset - sfd->file_offset);
        count += rv;

        if (rv < file_nbytes_to_send) {
            pt_Continuation op;

            op.arg1.osfd = sd->secret->md.osfd;
            op.in_fd = sfd->fd->secret->md.osfd;
            op.offset = offset;
            op.count = file_nbytes_to_send - rv;
            op.result.code = count;
            op.timeout = timeout;
            op.function = pt_linux_sendfile_cont;
            op.event = POLLOUT | POLLPRI;
            count = pt_Continue(&op);
            syserrno = op.syserrno;
            if (count == -1) {
                pt_MapError(_MD_linux_map_sendfile_error, syserrno);
                goto failed;
            }
        }
    }

    if (sfd->tlen != 0) {
        rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
        if (rv == -1) {
            count = -1;
            goto failed;
        }
        count += rv;
    }

failed:
    if (tcp_cork_enabled) {
        tcp_cork = 0;
        if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
                &tcp_cork, sizeof tcp_cork) == -1 && count != -1) {
            _PR_MD_MAP_SETSOCKOPT_ERROR(errno);
            count = -1;
        }
    }
    if (count != -1) {
        if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
            PR_Close(sd);
        }
        PR_ASSERT(count == sfd->hlen + sfd->tlen + file_nbytes_to_send);
    }
    return count;
}
#endif  /* LINUX */

#ifdef AIX
extern	int _pr_aix_send_file_use_disabled;
#endif

static PRInt32 pt_SendFile(
    PRFileDesc *sd, PRSendFileData *sfd,
    PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    if (pt_TestAbort()) return -1;
    /* The socket must be in blocking mode. */
    if (sd->secret->nonblocking)
    {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        return -1;
    }
#ifdef HPUX11
    return(pt_HPUXSendFile(sd, sfd, flags, timeout));
#elif defined(AIX)
#ifdef HAVE_SEND_FILE
	/*
	 * A bug in AIX 4.3.2 results in corruption of data transferred by
	 * send_file(); AIX patch PTF U463956 contains the fix.  A user can
	 * disable the use of send_file function in NSPR, when this patch is
	 * not installed on the system, by setting the envionment variable
	 * NSPR_AIX_SEND_FILE_USE_DISABLED to 1.
	 */
	if (_pr_aix_send_file_use_disabled)
		return(PR_EmulateSendFile(sd, sfd, flags, timeout));
	else
    	return(pt_AIXSendFile(sd, sfd, flags, timeout));
#else
	return(PR_EmulateSendFile(sd, sfd, flags, timeout));
    /* return(pt_AIXDispatchSendFile(sd, sfd, flags, timeout));*/
#endif /* HAVE_SEND_FILE */
#elif defined(SOLARIS)
#ifdef HAVE_SENDFILEV
    	return(pt_SolarisSendFile(sd, sfd, flags, timeout));
#else
	return(pt_SolarisDispatchSendFile(sd, sfd, flags, timeout));
#endif /* HAVE_SENDFILEV */
#elif defined(LINUX)
    	return(pt_LinuxSendFile(sd, sfd, flags, timeout));
#else
	return(PR_EmulateSendFile(sd, sfd, flags, timeout));
#endif
}

static PRInt32 pt_TransmitFile(
    PRFileDesc *sd, PRFileDesc *fd, const void *headers,
    PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
{
	PRSendFileData sfd;

	sfd.fd = fd;
	sfd.file_offset = 0;
	sfd.file_nbytes = 0;
	sfd.header = headers;
	sfd.hlen = hlen;
	sfd.trailer = NULL;
	sfd.tlen = 0;

	return(pt_SendFile(sd, &sfd, flags, timeout));
}  /* pt_TransmitFile */

static PRInt32 pt_AcceptRead(
    PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
    void *buf, PRInt32 amount, PRIntervalTime timeout)
{
    PRInt32 rv = -1;

    if (pt_TestAbort()) return rv;
    /* The socket must be in blocking mode. */
    if (sd->secret->nonblocking)
    {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        return rv;
    }

    rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
    return rv;
}  /* pt_AcceptRead */

static PRStatus pt_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
{
    PRIntn rv = -1;
    pt_SockLen addr_len = sizeof(PRNetAddr);

    if (pt_TestAbort()) return PR_FAILURE;

    rv = getsockname(
        fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
    if (rv == -1) {
        pt_MapError(_PR_MD_MAP_GETSOCKNAME_ERROR, errno);
        return PR_FAILURE;
    } else {
#ifdef _PR_HAVE_SOCKADDR_LEN
        /* ignore the sa_len field of struct sockaddr */
        if (addr)
        {
            addr->raw.family = ((struct sockaddr*)addr)->sa_family;
        }
#endif /* _PR_HAVE_SOCKADDR_LEN */
#ifdef _PR_INET6
		if (AF_INET6 == addr->raw.family)
			addr->raw.family = PR_AF_INET6;
#endif
        PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
        PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
        return PR_SUCCESS;
    }
}  /* pt_GetSockName */

static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
{
    PRIntn rv = -1;
    pt_SockLen addr_len = sizeof(PRNetAddr);

    if (pt_TestAbort()) return PR_FAILURE;

    rv = getpeername(
        fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);

    if (rv == -1) {
        pt_MapError(_PR_MD_MAP_GETPEERNAME_ERROR, errno);
        return PR_FAILURE;
    } else {
#ifdef _PR_HAVE_SOCKADDR_LEN
        /* ignore the sa_len field of struct sockaddr */
        if (addr)
        {
            addr->raw.family = ((struct sockaddr*)addr)->sa_family;
        }
#endif /* _PR_HAVE_SOCKADDR_LEN */
#ifdef _PR_INET6
		if (AF_INET6 == addr->raw.family)
        	addr->raw.family = PR_AF_INET6;
#endif
        PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
        PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
        return PR_SUCCESS;
    }
}  /* pt_GetPeerName */

static PRStatus pt_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
{
    PRIntn rv;
    pt_SockLen length;
    PRInt32 level, name;

    /*
     * PR_SockOpt_Nonblocking is a special case that does not
     * translate to a getsockopt() call
     */
    if (PR_SockOpt_Nonblocking == data->option)
    {
        data->value.non_blocking = fd->secret->nonblocking;
        return PR_SUCCESS;
    }

    rv = _PR_MapOptionName(data->option, &level, &name);
    if (PR_SUCCESS == rv)
    {
        switch (data->option)
        {
            case PR_SockOpt_Linger:
            {
                struct linger linger;
                length = sizeof(linger);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name, (char *) &linger, &length);
                PR_ASSERT((-1 == rv) || (sizeof(linger) == length));
                data->value.linger.polarity =
                    (linger.l_onoff) ? PR_TRUE : PR_FALSE;
                data->value.linger.linger =
                    PR_SecondsToInterval(linger.l_linger);
                break;
            }
            case PR_SockOpt_Reuseaddr:
            case PR_SockOpt_Keepalive:
            case PR_SockOpt_NoDelay:
            case PR_SockOpt_Broadcast:
            {
                PRIntn value;
                length = sizeof(PRIntn);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name, (char*)&value, &length);
                PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length));
                data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE;
                break;
            }
            case PR_SockOpt_McastLoopback:
            {
                PRUint8 xbool;
                length = sizeof(xbool);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&xbool, &length);
                PR_ASSERT((-1 == rv) || (sizeof(xbool) == length));
                data->value.mcast_loopback = (0 == xbool) ? PR_FALSE : PR_TRUE;
                break;
            }
            case PR_SockOpt_RecvBufferSize:
            case PR_SockOpt_SendBufferSize:
            case PR_SockOpt_MaxSegment:
            {
                PRIntn value;
                length = sizeof(PRIntn);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name, (char*)&value, &length);
                PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length));
                data->value.recv_buffer_size = value;
                break;
            }
            case PR_SockOpt_IpTimeToLive:
            case PR_SockOpt_IpTypeOfService:
            {
                length = sizeof(PRUintn);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&data->value.ip_ttl, &length);
                PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length));
                break;
            }
            case PR_SockOpt_McastTimeToLive:
            {
                PRUint8 ttl;
                length = sizeof(ttl);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&ttl, &length);
                PR_ASSERT((-1 == rv) || (sizeof(ttl) == length));
                data->value.mcast_ttl = ttl;
                break;
            }
            case PR_SockOpt_AddMember:
            case PR_SockOpt_DropMember:
            {
                struct ip_mreq mreq;
                length = sizeof(mreq);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name, (char*)&mreq, &length);
                PR_ASSERT((-1 == rv) || (sizeof(mreq) == length));
                data->value.add_member.mcaddr.inet.ip =
                    mreq.imr_multiaddr.s_addr;
                data->value.add_member.ifaddr.inet.ip =
                    mreq.imr_interface.s_addr;
                break;
            }
            case PR_SockOpt_McastInterface:
            {
                length = sizeof(data->value.mcast_if.inet.ip);
                rv = getsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&data->value.mcast_if.inet.ip, &length);
                PR_ASSERT((-1 == rv)
                    || (sizeof(data->value.mcast_if.inet.ip) == length));
                break;
            }
            default:
                PR_NOT_REACHED("Unknown socket option");
                break;
        }
        if (-1 == rv) _PR_MD_MAP_GETSOCKOPT_ERROR(errno);
    }
    return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
}  /* pt_GetSocketOption */

static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data)
{
    PRIntn rv;
    PRInt32 level, name;

    /*
     * PR_SockOpt_Nonblocking is a special case that does not
     * translate to a setsockopt call.
     */
    if (PR_SockOpt_Nonblocking == data->option)
    {
        fd->secret->nonblocking = data->value.non_blocking;
        return PR_SUCCESS;
    }

    rv = _PR_MapOptionName(data->option, &level, &name);
    if (PR_SUCCESS == rv)
    {
        switch (data->option)
        {
            case PR_SockOpt_Linger:
            {
                struct linger linger;
                linger.l_onoff = data->value.linger.polarity;
                linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger);
                rv = setsockopt(
                    fd->secret->md.osfd, level, name, (char*)&linger, sizeof(linger));
                break;
            }
            case PR_SockOpt_Reuseaddr:
            case PR_SockOpt_Keepalive:
            case PR_SockOpt_NoDelay:
            case PR_SockOpt_Broadcast:
            {
                PRIntn value = (data->value.reuse_addr) ? 1 : 0;
                rv = setsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&value, sizeof(PRIntn));
#ifdef LINUX
                /* for pt_LinuxSendFile */
                if (name == TCP_NODELAY && rv == 0) {
                    fd->secret->md.tcp_nodelay = value;
                }
#endif
                break;
            }
            case PR_SockOpt_McastLoopback:
            {
                PRUint8 xbool = data->value.mcast_loopback ? 1 : 0;
                rv = setsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&xbool, sizeof(xbool));
                break;
            }
            case PR_SockOpt_RecvBufferSize:
            case PR_SockOpt_SendBufferSize:
            case PR_SockOpt_MaxSegment:
            {
                PRIntn value = data->value.recv_buffer_size;
                rv = setsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&value, sizeof(PRIntn));
                break;
            }
            case PR_SockOpt_IpTimeToLive:
            case PR_SockOpt_IpTypeOfService:
            {
                rv = setsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&data->value.ip_ttl, sizeof(PRUintn));
                break;
            }
            case PR_SockOpt_McastTimeToLive:
            {
                PRUint8 ttl = data->value.mcast_ttl;
                rv = setsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&ttl, sizeof(ttl));
                break;
            }
            case PR_SockOpt_AddMember:
            case PR_SockOpt_DropMember:
            {
                struct ip_mreq mreq;
                mreq.imr_multiaddr.s_addr =
                    data->value.add_member.mcaddr.inet.ip;
                mreq.imr_interface.s_addr =
                    data->value.add_member.ifaddr.inet.ip;
                rv = setsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&mreq, sizeof(mreq));
                break;
            }
            case PR_SockOpt_McastInterface:
            {
                rv = setsockopt(
                    fd->secret->md.osfd, level, name,
                    (char*)&data->value.mcast_if.inet.ip,
                    sizeof(data->value.mcast_if.inet.ip));
                break;
            }
            default:
                PR_NOT_REACHED("Unknown socket option");
                break;
        }
        if (-1 == rv) _PR_MD_MAP_SETSOCKOPT_ERROR(errno);
    }
    return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
}  /* pt_SetSocketOption */

/*****************************************************************************/
/****************************** I/O method objects ***************************/
/*****************************************************************************/

static PRIOMethods _pr_file_methods = {
    PR_DESC_FILE,
    pt_Close,
    pt_Read,
    pt_Write,
    pt_Available_f,
    pt_Available64_f,
    pt_Fsync,
    pt_Seek,
    pt_Seek64,
    pt_FileInfo,
    pt_FileInfo64,
    (PRWritevFN)_PR_InvalidInt,        
    (PRConnectFN)_PR_InvalidStatus,        
    (PRAcceptFN)_PR_InvalidDesc,        
    (PRBindFN)_PR_InvalidStatus,        
    (PRListenFN)_PR_InvalidStatus,        
    (PRShutdownFN)_PR_InvalidStatus,    
    (PRRecvFN)_PR_InvalidInt,        
    (PRSendFN)_PR_InvalidInt,        
    (PRRecvfromFN)_PR_InvalidInt,    
    (PRSendtoFN)_PR_InvalidInt,        
    pt_Poll,
    (PRAcceptreadFN)_PR_InvalidInt,   
    (PRTransmitfileFN)_PR_InvalidInt, 
    (PRGetsocknameFN)_PR_InvalidStatus,    
    (PRGetpeernameFN)_PR_InvalidStatus,    
    (PRReservedFN)_PR_InvalidInt,    
    (PRReservedFN)_PR_InvalidInt,    
    (PRGetsocketoptionFN)_PR_InvalidStatus,
    (PRSetsocketoptionFN)_PR_InvalidStatus,
    (PRSendfileFN)_PR_InvalidInt, 
    (PRConnectcontinueFN)_PR_InvalidStatus, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt
};

static PRIOMethods _pr_pipe_methods = {
    PR_DESC_PIPE,
    pt_Close,
    pt_Read,
    pt_Write,
    pt_Available_s,
    pt_Available64_s,
    pt_Synch,
    (PRSeekFN)_PR_InvalidInt,
    (PRSeek64FN)_PR_InvalidInt64,
    (PRFileInfoFN)_PR_InvalidStatus,
    (PRFileInfo64FN)_PR_InvalidStatus,
    (PRWritevFN)_PR_InvalidInt,        
    (PRConnectFN)_PR_InvalidStatus,        
    (PRAcceptFN)_PR_InvalidDesc,        
    (PRBindFN)_PR_InvalidStatus,        
    (PRListenFN)_PR_InvalidStatus,        
    (PRShutdownFN)_PR_InvalidStatus,    
    (PRRecvFN)_PR_InvalidInt,        
    (PRSendFN)_PR_InvalidInt,        
    (PRRecvfromFN)_PR_InvalidInt,    
    (PRSendtoFN)_PR_InvalidInt,        
    pt_Poll,
    (PRAcceptreadFN)_PR_InvalidInt,   
    (PRTransmitfileFN)_PR_InvalidInt, 
    (PRGetsocknameFN)_PR_InvalidStatus,    
    (PRGetpeernameFN)_PR_InvalidStatus,    
    (PRReservedFN)_PR_InvalidInt,    
    (PRReservedFN)_PR_InvalidInt,    
    (PRGetsocketoptionFN)_PR_InvalidStatus,
    (PRSetsocketoptionFN)_PR_InvalidStatus,
    (PRSendfileFN)_PR_InvalidInt, 
    (PRConnectcontinueFN)_PR_InvalidStatus, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt
};

static PRIOMethods _pr_tcp_methods = {
    PR_DESC_SOCKET_TCP,
    pt_Close,
    pt_SocketRead,
    pt_SocketWrite,
    pt_Available_s,
    pt_Available64_s,
    pt_Synch,
    (PRSeekFN)_PR_InvalidInt,
    (PRSeek64FN)_PR_InvalidInt64,
    (PRFileInfoFN)_PR_InvalidStatus,
    (PRFileInfo64FN)_PR_InvalidStatus,
    pt_Writev,
    pt_Connect,
    pt_Accept,
    pt_Bind,
    pt_Listen,
    pt_Shutdown,
    pt_Recv,
    pt_Send,
    (PRRecvfromFN)_PR_InvalidInt,
    (PRSendtoFN)_PR_InvalidInt,
    pt_Poll,
    pt_AcceptRead,
    pt_TransmitFile,
    pt_GetSockName,
    pt_GetPeerName,
    (PRReservedFN)_PR_InvalidInt,
    (PRReservedFN)_PR_InvalidInt,
    pt_GetSocketOption,
    pt_SetSocketOption,
    pt_SendFile, 
    pt_ConnectContinue,
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt
};

static PRIOMethods _pr_udp_methods = {
    PR_DESC_SOCKET_UDP,
    pt_Close,
    pt_SocketRead,
    pt_SocketWrite,
    pt_Available_s,
    pt_Available64_s,
    pt_Synch,
    (PRSeekFN)_PR_InvalidInt,
    (PRSeek64FN)_PR_InvalidInt64,
    (PRFileInfoFN)_PR_InvalidStatus,
    (PRFileInfo64FN)_PR_InvalidStatus,
    pt_Writev,
    pt_Connect,
    (PRAcceptFN)_PR_InvalidDesc,
    pt_Bind,
    pt_Listen,
    pt_Shutdown,
    pt_Recv,
    pt_Send,
    pt_RecvFrom,
    pt_SendTo,
    pt_Poll,
    (PRAcceptreadFN)_PR_InvalidInt,
    (PRTransmitfileFN)_PR_InvalidInt,
    pt_GetSockName,
    pt_GetPeerName,
    (PRReservedFN)_PR_InvalidInt,
    (PRReservedFN)_PR_InvalidInt,
    pt_GetSocketOption,
    pt_SetSocketOption,
    (PRSendfileFN)_PR_InvalidInt, 
    (PRConnectcontinueFN)_PR_InvalidStatus, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt
};

static PRIOMethods _pr_socketpollfd_methods = {
    (PRDescType) 0,
    (PRCloseFN)_PR_InvalidStatus,
    (PRReadFN)_PR_InvalidInt,
    (PRWriteFN)_PR_InvalidInt,
    (PRAvailableFN)_PR_InvalidInt,
    (PRAvailable64FN)_PR_InvalidInt64,
    (PRFsyncFN)_PR_InvalidStatus,
    (PRSeekFN)_PR_InvalidInt,
    (PRSeek64FN)_PR_InvalidInt64,
    (PRFileInfoFN)_PR_InvalidStatus,
    (PRFileInfo64FN)_PR_InvalidStatus,
    (PRWritevFN)_PR_InvalidInt,        
    (PRConnectFN)_PR_InvalidStatus,        
    (PRAcceptFN)_PR_InvalidDesc,        
    (PRBindFN)_PR_InvalidStatus,        
    (PRListenFN)_PR_InvalidStatus,        
    (PRShutdownFN)_PR_InvalidStatus,    
    (PRRecvFN)_PR_InvalidInt,        
    (PRSendFN)_PR_InvalidInt,        
    (PRRecvfromFN)_PR_InvalidInt,    
    (PRSendtoFN)_PR_InvalidInt,        
	pt_Poll,
    (PRAcceptreadFN)_PR_InvalidInt,   
    (PRTransmitfileFN)_PR_InvalidInt, 
    (PRGetsocknameFN)_PR_InvalidStatus,    
    (PRGetpeernameFN)_PR_InvalidStatus,    
    (PRReservedFN)_PR_InvalidInt,    
    (PRReservedFN)_PR_InvalidInt,    
    (PRGetsocketoptionFN)_PR_InvalidStatus,
    (PRSetsocketoptionFN)_PR_InvalidStatus,
    (PRSendfileFN)_PR_InvalidInt, 
    (PRConnectcontinueFN)_PR_InvalidStatus, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt, 
    (PRReservedFN)_PR_InvalidInt
};

#if defined(HPUX) || defined(OSF1) || defined(SOLARIS) || defined (IRIX) \
    || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
    || defined(AIX) || defined(FREEBSD) || defined(NETBSD) \
    || defined(OPENBSD) || defined(BSDI) || defined(NTO) \
    || defined(DARWIN) || defined(UNIXWARE) || defined(RISCOS) \
    || defined(SYMBIAN)
#define _PR_FCNTL_FLAGS O_NONBLOCK
#else
#error "Can't determine architecture"
#endif

/*
 * Put a Unix file descriptor in non-blocking mode.
 */
static void pt_MakeFdNonblock(PRIntn osfd)
{
    PRIntn flags;
    flags = fcntl(osfd, F_GETFL, 0);
    flags |= _PR_FCNTL_FLAGS;
    (void)fcntl(osfd, F_SETFL, flags);
}

/*
 * Put a Unix socket fd in non-blocking mode that can
 * ideally be inherited by an accepted socket.
 *
 * Why doesn't pt_MakeFdNonblock do?  This is to deal with
 * the special case of HP-UX.  HP-UX has three kinds of
 * non-blocking modes for sockets: the fcntl() O_NONBLOCK
 * and O_NDELAY flags and ioctl() FIOSNBIO request.  Only
 * the ioctl() FIOSNBIO form of non-blocking mode is
 * inherited by an accepted socket.
 *
 * Other platforms just use the generic pt_MakeFdNonblock
 * to put a socket in non-blocking mode.
 */
#ifdef HPUX
static void pt_MakeSocketNonblock(PRIntn osfd)
{
    PRIntn one = 1;
    (void)ioctl(osfd, FIOSNBIO, &one);
}
#else
#define pt_MakeSocketNonblock pt_MakeFdNonblock
#endif

static PRFileDesc *pt_SetMethods(
    PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported)
{
    PRFileDesc *fd = _PR_Getfd();
    
    if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    else
    {
        fd->secret->md.osfd = osfd;
        fd->secret->state = _PR_FILEDESC_OPEN;
        if (imported) fd->secret->inheritable = _PR_TRI_UNKNOWN;
        else
        {
            /* By default, a Unix fd is not closed on exec. */
#ifdef DEBUG
            PRIntn flags;
            flags = fcntl(osfd, F_GETFD, 0);
            PR_ASSERT(0 == flags);
#endif
            fd->secret->inheritable = _PR_TRI_TRUE;
        }
        switch (type)
        {
            case PR_DESC_FILE:
                fd->methods = PR_GetFileMethods();
                break;
            case PR_DESC_SOCKET_TCP:
                fd->methods = PR_GetTCPMethods();
#ifdef _PR_ACCEPT_INHERIT_NONBLOCK
                if (!isAcceptedSocket) pt_MakeSocketNonblock(osfd);
#else
                pt_MakeSocketNonblock(osfd);
#endif
                break;
            case PR_DESC_SOCKET_UDP:
                fd->methods = PR_GetUDPMethods();
                pt_MakeFdNonblock(osfd);
                break;
            case PR_DESC_PIPE:
                fd->methods = PR_GetPipeMethods();
                pt_MakeFdNonblock(osfd);
                break;
            default:
                break;
        }
    }
    return fd;
}  /* pt_SetMethods */

PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)
{
    return &_pr_file_methods;
}  /* PR_GetFileMethods */

PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void)
{
    return &_pr_pipe_methods;
}  /* PR_GetPipeMethods */

PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods(void)
{
    return &_pr_tcp_methods;
}  /* PR_GetTCPMethods */

PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods(void)
{
    return &_pr_udp_methods;
}  /* PR_GetUDPMethods */

static const PRIOMethods* PR_GetSocketPollFdMethods(void)
{
    return &_pr_socketpollfd_methods;
}  /* PR_GetSocketPollFdMethods */

PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
    PRInt32 osfd, const PRIOMethods *methods)
{
    PRFileDesc *fd = _PR_Getfd();

    if (NULL == fd) goto failed;

    fd->methods = methods;
    fd->secret->md.osfd = osfd;
    /* Make fd non-blocking */
    if (osfd > 2)
    {
        /* Don't mess around with stdin, stdout or stderr */
        if (&_pr_tcp_methods == methods) pt_MakeSocketNonblock(osfd);
        else pt_MakeFdNonblock(osfd);
    }
    fd->secret->state = _PR_FILEDESC_OPEN;
    fd->secret->inheritable = _PR_TRI_UNKNOWN;
    return fd;
    
failed:
    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    return fd;
}  /* PR_AllocFileDesc */

#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
#if defined(_PR_INET6_PROBE)
extern PRBool _pr_ipv6_is_present(void);
PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket()
{
PRInt32 osfd;

#if defined(DARWIN)
    /*
     * Disable IPv6 if Darwin version is less than 7.0.0 (OS X 10.3).  IPv6 on
     * lesser versions is not ready for general use (see bug 222031).
     */
    {
        struct utsname u;
        if (uname(&u) != 0 || atoi(u.release) < 7)
            return PR_FALSE;
    }
#endif

    /*
     * HP-UX only: HP-UX IPv6 Porting Guide (dated February 2001)
     * suggests that we call open("/dev/ip6", O_RDWR) to determine
     * whether IPv6 APIs and the IPv6 stack are on the system.
     * Our portable test below seems to work fine, so I am using it.
     */
    osfd = socket(AF_INET6, SOCK_STREAM, 0);
    if (osfd != -1) {
        close(osfd);
        return PR_TRUE;
    }
    return PR_FALSE;
}
#endif	/* _PR_INET6_PROBE */
#endif

PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
{
    PRIntn osfd;
    PRDescType ftype;
    PRFileDesc *fd = NULL;
#if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
    PRInt32 tmp_domain = domain;
#endif

    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (pt_TestAbort()) return NULL;

    if (PF_INET != domain
        && PR_AF_INET6 != domain
        && PF_UNIX != domain)
    {
        PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
        return fd;
    }
	if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP;
	else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP;
	else
	{
		(void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
		return fd;
	}
#if defined(_PR_INET6_PROBE)
	if (PR_AF_INET6 == domain)
		domain = _pr_ipv6_is_present() ? AF_INET6 : AF_INET;
#elif defined(_PR_INET6) 
	if (PR_AF_INET6 == domain)
		domain = AF_INET6;
#else
	if (PR_AF_INET6 == domain)
		domain = AF_INET;
#endif

    osfd = socket(domain, type, proto);
    if (osfd == -1) pt_MapError(_PR_MD_MAP_SOCKET_ERROR, errno);
    else
    {
#ifdef _PR_IPV6_V6ONLY_PROBE
        if ((domain == AF_INET6) && _pr_ipv6_v6only_on_by_default)
        {
            int on = 0;
            (void)setsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY,
                    &on, sizeof(on));
        }
#endif
        fd = pt_SetMethods(osfd, ftype, PR_FALSE, PR_FALSE);
        if (fd == NULL) close(osfd);
    }
#ifdef _PR_NEED_SECRET_AF
    if (fd != NULL) fd->secret->af = domain;
#endif
#if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
	if (fd != NULL) {
		/*
		 * For platforms with no support for IPv6 
		 * create layered socket for IPv4-mapped IPv6 addresses
		 */
		if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) {
			if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) {
				PR_Close(fd);
				fd = NULL;
			}
		}
	}
#endif
    return fd;
}  /* PR_Socket */

/*****************************************************************************/
/****************************** I/O public methods ***************************/
/*****************************************************************************/

PR_IMPLEMENT(PRFileDesc*) PR_OpenFile(
    const char *name, PRIntn flags, PRIntn mode)
{
    PRFileDesc *fd = NULL;
    PRIntn syserrno, osfd = -1, osflags = 0;;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (pt_TestAbort()) return NULL;

    if (flags & PR_RDONLY) osflags |= O_RDONLY;
    if (flags & PR_WRONLY) osflags |= O_WRONLY;
    if (flags & PR_RDWR) osflags |= O_RDWR;
    if (flags & PR_APPEND) osflags |= O_APPEND;
    if (flags & PR_TRUNCATE) osflags |= O_TRUNC;
    if (flags & PR_EXCL) osflags |= O_EXCL;
    if (flags & PR_SYNC)
    {
#if defined(O_SYNC)
        osflags |= O_SYNC;
#elif defined(O_FSYNC)
        osflags |= O_FSYNC;
#else
#error "Neither O_SYNC nor O_FSYNC is defined on this platform"
#endif
    }

    /*
    ** We have to hold the lock across the creation in order to
    ** enforce the sematics of PR_Rename(). (see the latter for
    ** more details)
    */
    if (flags & PR_CREATE_FILE)
    {
        osflags |= O_CREAT;
        if (NULL !=_pr_rename_lock)
            PR_Lock(_pr_rename_lock);
    }

    osfd = _md_iovector._open64(name, osflags, mode);
    syserrno = errno;

    if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
        PR_Unlock(_pr_rename_lock);

    if (osfd == -1)
        pt_MapError(_PR_MD_MAP_OPEN_ERROR, syserrno);
    else
    {
        fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE, PR_FALSE);
        if (fd == NULL) close(osfd);  /* $$$ whoops! this is bad $$$ */
    }
    return fd;
}  /* PR_OpenFile */

PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
{
    return PR_OpenFile(name, flags, mode);
}  /* PR_Open */

PR_IMPLEMENT(PRStatus) PR_Delete(const char *name)
{
    PRIntn rv = -1;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (pt_TestAbort()) return PR_FAILURE;

    rv = unlink(name);

    if (rv == -1) {
        pt_MapError(_PR_MD_MAP_UNLINK_ERROR, errno);
        return PR_FAILURE;
    } else
        return PR_SUCCESS;
}  /* PR_Delete */

PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how)
{
    PRIntn rv;

    if (pt_TestAbort()) return PR_FAILURE;

    switch (how)
    {
    case PR_ACCESS_READ_OK:
        rv =  access(name, R_OK);
        break;
    case PR_ACCESS_WRITE_OK:
        rv = access(name, W_OK);
        break;
    case PR_ACCESS_EXISTS:
    default:
        rv = access(name, F_OK);
    }
    if (0 == rv) return PR_SUCCESS;
    pt_MapError(_PR_MD_MAP_ACCESS_ERROR, errno);
    return PR_FAILURE;
    
}  /* PR_Access */

PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)
{
    PRInt32 rv = _PR_MD_GETFILEINFO(fn, info);
    return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
}  /* PR_GetFileInfo */

PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
{
    PRInt32 rv;

    if (!_pr_initialized) _PR_ImplicitInitialization();
    rv = _PR_MD_GETFILEINFO64(fn, info);
    return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
}  /* PR_GetFileInfo64 */

PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to)
{
    PRIntn rv = -1;

    if (pt_TestAbort()) return PR_FAILURE;

    /*
    ** We have to acquire a lock here to stiffle anybody trying to create
    ** a new file at the same time. And we have to hold that lock while we
    ** test to see if the file exists and do the rename. The other place
    ** where the lock is held is in PR_Open() when possibly creating a 
    ** new file.
    */

    PR_Lock(_pr_rename_lock);
    rv = access(to, F_OK);
    if (0 == rv)
    {
        PR_SetError(PR_FILE_EXISTS_ERROR, 0);
        rv = -1;
    }
    else
    {
        rv = rename(from, to);
        if (rv == -1)
            pt_MapError(_PR_MD_MAP_RENAME_ERROR, errno);
    }
    PR_Unlock(_pr_rename_lock);
    return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
}  /* PR_Rename */

PR_IMPLEMENT(PRStatus) PR_CloseDir(PRDir *dir)
{
    if (pt_TestAbort()) return PR_FAILURE;

    if (NULL != dir->md.d)
    {
        if (closedir(dir->md.d) == -1)
        {
            _PR_MD_MAP_CLOSEDIR_ERROR(errno);
            return PR_FAILURE;
        }
        dir->md.d = NULL;
        PR_DELETE(dir);
    }
    return PR_SUCCESS;
}  /* PR_CloseDir */

PR_IMPLEMENT(PRStatus) PR_MakeDir(const char *name, PRIntn mode)
{
    PRInt32 rv = -1;

    if (pt_TestAbort()) return PR_FAILURE;

    /*
    ** This lock is used to enforce rename semantics as described
    ** in PR_Rename.
    */
    if (NULL !=_pr_rename_lock)
        PR_Lock(_pr_rename_lock);
    rv = mkdir(name, mode);
    if (-1 == rv)
        pt_MapError(_PR_MD_MAP_MKDIR_ERROR, errno);
    if (NULL !=_pr_rename_lock)
        PR_Unlock(_pr_rename_lock);

    return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
}  /* PR_Makedir */

PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode)
{
    return PR_MakeDir(name, mode);
}  /* PR_Mkdir */

PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name)
{
    PRInt32 rv;

    if (pt_TestAbort()) return PR_FAILURE;

    rv = rmdir(name);
    if (0 == rv) {
    return PR_SUCCESS;
    } else {
    pt_MapError(_PR_MD_MAP_RMDIR_ERROR, errno);
    return PR_FAILURE;
    }
}  /* PR_Rmdir */


PR_IMPLEMENT(PRDir*) PR_OpenDir(const char *name)
{
    DIR *osdir;
    PRDir *dir = NULL;

    if (pt_TestAbort()) return dir;

    osdir = opendir(name);
    if (osdir == NULL)
        pt_MapError(_PR_MD_MAP_OPENDIR_ERROR, errno);
    else
    {
        dir = PR_NEWZAP(PRDir);
        if (dir)
            dir->md.d = osdir;
        else
            (void)closedir(osdir);
    }
    return dir;
}  /* PR_OpenDir */

static PRInt32 _pr_poll_with_poll(
    PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
    PRInt32 ready = 0;
    /*
     * For restarting poll() if it is interrupted by a signal.
     * We use these variables to figure out how much time has
     * elapsed and how much of the timeout still remains.
     */
    PRIntervalTime start, elapsed, remaining;

    if (pt_TestAbort()) return -1;

    if (0 == npds) PR_Sleep(timeout);
    else
    {
#define STACK_POLL_DESC_COUNT 64
        struct pollfd stack_syspoll[STACK_POLL_DESC_COUNT];
        struct pollfd *syspoll;
        PRIntn index, msecs;

        if (npds <= STACK_POLL_DESC_COUNT)
        {
            syspoll = stack_syspoll;
        }
        else
        {
            PRThread *me = PR_GetCurrentThread();
            if (npds > me->syspoll_count)
            {
                PR_Free(me->syspoll_list);
                me->syspoll_list =
                    (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
                if (NULL == me->syspoll_list)
                {
                    me->syspoll_count = 0;
                    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
                    return -1;
                }
                me->syspoll_count = npds;
            }
            syspoll = me->syspoll_list;
        }

        for (index = 0; index < npds; ++index)
        {
            PRInt16 in_flags_read = 0, in_flags_write = 0;
            PRInt16 out_flags_read = 0, out_flags_write = 0;

            if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
            {
                if (pds[index].in_flags & PR_POLL_READ)
                {
                    in_flags_read = (pds[index].fd->methods->poll)(
                        pds[index].fd,
                        pds[index].in_flags & ~PR_POLL_WRITE,
                        &out_flags_read);
                }
                if (pds[index].in_flags & PR_POLL_WRITE)
                {
                    in_flags_write = (pds[index].fd->methods->poll)(
                        pds[index].fd,
                        pds[index].in_flags & ~PR_POLL_READ,
                        &out_flags_write);
                }
                if ((0 != (in_flags_read & out_flags_read))
                || (0 != (in_flags_write & out_flags_write)))
                {
                    /* this one is ready right now */
                    if (0 == ready)
                    {
                        /*
                         * We will return without calling the system
                         * poll function.  So zero the out_flags
                         * fields of all the poll descriptors before
                         * this one.
                         */
                        int i;
                        for (i = 0; i < index; i++)
                        {
                            pds[i].out_flags = 0;
                        }
                    }
                    ready += 1;
                    pds[index].out_flags = out_flags_read | out_flags_write;
                }
                else
                {
                    /* now locate the NSPR layer at the bottom of the stack */
                    PRFileDesc *bottom = PR_GetIdentitiesLayer(
                        pds[index].fd, PR_NSPR_IO_LAYER);
                    PR_ASSERT(NULL != bottom);  /* what to do about that? */
                    pds[index].out_flags = 0;  /* pre-condition */
                    if ((NULL != bottom)
                    && (_PR_FILEDESC_OPEN == bottom->secret->state))
                    {
                        if (0 == ready)
                        {
                            syspoll[index].fd = bottom->secret->md.osfd;
                            syspoll[index].events = 0;
                            if (in_flags_read & PR_POLL_READ)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_READ_SYS_READ;
                                syspoll[index].events |= POLLIN;
                            }
                            if (in_flags_read & PR_POLL_WRITE)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_READ_SYS_WRITE;
                                syspoll[index].events |= POLLOUT;
                            }
                            if (in_flags_write & PR_POLL_READ)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_WRITE_SYS_READ;
                                syspoll[index].events |= POLLIN;
                            }
                            if (in_flags_write & PR_POLL_WRITE)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_WRITE_SYS_WRITE;
                                syspoll[index].events |= POLLOUT;
                            }
                            if (pds[index].in_flags & PR_POLL_EXCEPT)
                                syspoll[index].events |= POLLPRI;
                        }
                    }
                    else
                    {
                        if (0 == ready)
                        {
                            int i;
                            for (i = 0; i < index; i++)
                            {
                                pds[i].out_flags = 0;
                            }
                        }
                        ready += 1;  /* this will cause an abrupt return */
                        pds[index].out_flags = PR_POLL_NVAL;  /* bogii */
                    }
                }
            }
            else
            {
                /* make poll() ignore this entry */
                syspoll[index].fd = -1;
                syspoll[index].events = 0;
                pds[index].out_flags = 0;
            }
        }
        if (0 == ready)
        {
            switch (timeout)
            {
            case PR_INTERVAL_NO_WAIT: msecs = 0; break;
            case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break;
            default:
                msecs = PR_IntervalToMilliseconds(timeout);
                start = PR_IntervalNow();
            }

retry:
            ready = poll(syspoll, npds, msecs);
            if (-1 == ready)
            {
                PRIntn oserror = errno;

                if (EINTR == oserror)
                {
                    if (timeout == PR_INTERVAL_NO_TIMEOUT)
                        goto retry;
                    else if (timeout == PR_INTERVAL_NO_WAIT)
                        ready = 0;  /* don't retry, just time out */
                    else
                    {
                        elapsed = (PRIntervalTime) (PR_IntervalNow()
                                - start);
                        if (elapsed > timeout)
                            ready = 0;  /* timed out */
                        else
                        {
                            remaining = timeout - elapsed;
                            msecs = PR_IntervalToMilliseconds(remaining);
                            goto retry;
                        }
                    }
                }
                else
                {
                    _PR_MD_MAP_POLL_ERROR(oserror);
                }
            }
            else if (ready > 0)
            {
                for (index = 0; index < npds; ++index)
                {
                    PRInt16 out_flags = 0;
                    if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
                    {
                        if (0 != syspoll[index].revents)
                        {
                            if (syspoll[index].revents & POLLIN)
                            {
                                if (pds[index].out_flags
                                & _PR_POLL_READ_SYS_READ)
                                {
                                    out_flags |= PR_POLL_READ;
                                }
                                if (pds[index].out_flags
                                & _PR_POLL_WRITE_SYS_READ)
                                {
                                    out_flags |= PR_POLL_WRITE;
                                }
                            }
                            if (syspoll[index].revents & POLLOUT)
                            {
                                if (pds[index].out_flags
                                & _PR_POLL_READ_SYS_WRITE)
                                {
                                    out_flags |= PR_POLL_READ;
                                }
                                if (pds[index].out_flags
                                & _PR_POLL_WRITE_SYS_WRITE)
                                {
                                    out_flags |= PR_POLL_WRITE;
                                }
                            }
                            if (syspoll[index].revents & POLLPRI)
                                out_flags |= PR_POLL_EXCEPT;
                            if (syspoll[index].revents & POLLERR)
                                out_flags |= PR_POLL_ERR;
                            if (syspoll[index].revents & POLLNVAL)
                                out_flags |= PR_POLL_NVAL;
                            if (syspoll[index].revents & POLLHUP)
                                out_flags |= PR_POLL_HUP;
                        }
                    }
                    pds[index].out_flags = out_flags;
                }
            }
        }
    }
    return ready;

} /* _pr_poll_with_poll */

#if defined(_PR_POLL_WITH_SELECT)
/*
 * OSF1 and HPUX report the POLLHUP event for a socket when the
 * shutdown(SHUT_WR) operation is called for the remote end, even though
 * the socket is still writeable. Use select(), instead of poll(), to
 * workaround this problem.
 */
static PRInt32 _pr_poll_with_select(
    PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
    PRInt32 ready = 0;
    /*
     * For restarting select() if it is interrupted by a signal.
     * We use these variables to figure out how much time has
     * elapsed and how much of the timeout still remains.
     */
    PRIntervalTime start, elapsed, remaining;

    if (pt_TestAbort()) return -1;

    if (0 == npds) PR_Sleep(timeout);
    else
    {
#define STACK_POLL_DESC_COUNT 64
        int stack_selectfd[STACK_POLL_DESC_COUNT];
        int *selectfd;
		fd_set rd, wr, ex, *rdp = NULL, *wrp = NULL, *exp = NULL;
		struct timeval tv, *tvp;
        PRIntn index, msecs, maxfd = 0;

        if (npds <= STACK_POLL_DESC_COUNT)
        {
            selectfd = stack_selectfd;
        }
        else
        {
            PRThread *me = PR_GetCurrentThread();
            if (npds > me->selectfd_count)
            {
                PR_Free(me->selectfd_list);
                me->selectfd_list = (int *)PR_MALLOC(npds * sizeof(int));
                if (NULL == me->selectfd_list)
                {
                    me->selectfd_count = 0;
                    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
                    return -1;
                }
                me->selectfd_count = npds;
            }
            selectfd = me->selectfd_list;
        }
		FD_ZERO(&rd);
		FD_ZERO(&wr);
		FD_ZERO(&ex);

        for (index = 0; index < npds; ++index)
        {
            PRInt16 in_flags_read = 0, in_flags_write = 0;
            PRInt16 out_flags_read = 0, out_flags_write = 0;

            if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
            {
                if (pds[index].in_flags & PR_POLL_READ)
                {
                    in_flags_read = (pds[index].fd->methods->poll)(
                        pds[index].fd,
                        pds[index].in_flags & ~PR_POLL_WRITE,
                        &out_flags_read);
                }
                if (pds[index].in_flags & PR_POLL_WRITE)
                {
                    in_flags_write = (pds[index].fd->methods->poll)(
                        pds[index].fd,
                        pds[index].in_flags & ~PR_POLL_READ,
                        &out_flags_write);
                }
                if ((0 != (in_flags_read & out_flags_read))
                || (0 != (in_flags_write & out_flags_write)))
                {
                    /* this one is ready right now */
                    if (0 == ready)
                    {
                        /*
                         * We will return without calling the system
                         * poll function.  So zero the out_flags
                         * fields of all the poll descriptors before
                         * this one.
                         */
                        int i;
                        for (i = 0; i < index; i++)
                        {
                            pds[i].out_flags = 0;
                        }
                    }
                    ready += 1;
                    pds[index].out_flags = out_flags_read | out_flags_write;
                }
                else
                {
                    /* now locate the NSPR layer at the bottom of the stack */
                    PRFileDesc *bottom = PR_GetIdentitiesLayer(
                        pds[index].fd, PR_NSPR_IO_LAYER);
                    PR_ASSERT(NULL != bottom);  /* what to do about that? */
                    pds[index].out_flags = 0;  /* pre-condition */
                    if ((NULL != bottom)
                    && (_PR_FILEDESC_OPEN == bottom->secret->state))
                    {
                        if (0 == ready)
                        {
                            PRBool add_to_rd = PR_FALSE;
                            PRBool add_to_wr = PR_FALSE;
                            PRBool add_to_ex = PR_FALSE;

                            selectfd[index] = bottom->secret->md.osfd;
                            if (in_flags_read & PR_POLL_READ)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_READ_SYS_READ;
                                add_to_rd = PR_TRUE;
                            }
                            if (in_flags_read & PR_POLL_WRITE)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_READ_SYS_WRITE;
                                add_to_wr = PR_TRUE;
                            }
                            if (in_flags_write & PR_POLL_READ)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_WRITE_SYS_READ;
                                add_to_rd = PR_TRUE;
                            }
                            if (in_flags_write & PR_POLL_WRITE)
                            {
                                pds[index].out_flags |=
                                    _PR_POLL_WRITE_SYS_WRITE;
                                add_to_wr = PR_TRUE;
                            }
                            if (pds[index].in_flags & PR_POLL_EXCEPT)
                            {
                                add_to_ex = PR_TRUE;
                            }
                            if ((selectfd[index] > maxfd) &&
                                    (add_to_rd || add_to_wr || add_to_ex))
                            {
                                maxfd = selectfd[index];
                                /*
                                 * If maxfd is too large to be used with
                                 * select, fall back to calling poll.
                                 */
                                if (maxfd >= FD_SETSIZE)
                                    break;
                            }
                            if (add_to_rd)
                            {
                                FD_SET(bottom->secret->md.osfd, &rd);
                                rdp = &rd;
                            }
                            if (add_to_wr)
                            {
                                FD_SET(bottom->secret->md.osfd, &wr);
                                wrp = &wr;
                            }
                            if (add_to_ex)
                            {
                                FD_SET(bottom->secret->md.osfd, &ex);
                                exp = &ex;
                            }
                        }
                    }
                    else
                    {
                        if (0 == ready)
                        {
                            int i;
                            for (i = 0; i < index; i++)
                            {
                                pds[i].out_flags = 0;
                            }
                        }
                        ready += 1;  /* this will cause an abrupt return */
                        pds[index].out_flags = PR_POLL_NVAL;  /* bogii */
                    }
                }
            }
            else
            {
                pds[index].out_flags = 0;
            }
        }
        if (0 == ready)
        {
			if (maxfd >= FD_SETSIZE)
			{
				/*
				 * maxfd too large to be used with select, fall back to
				 * calling poll
				 */
				return(_pr_poll_with_poll(pds, npds, timeout));
			}
            switch (timeout)
            {
            case PR_INTERVAL_NO_WAIT:
				tv.tv_sec = 0;
				tv.tv_usec = 0;
				tvp = &tv;
				break;
            case PR_INTERVAL_NO_TIMEOUT:
				tvp = NULL;
				break;
            default:
                msecs = PR_IntervalToMilliseconds(timeout);
				tv.tv_sec = msecs/PR_MSEC_PER_SEC;
				tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
				tvp = &tv;
                start = PR_IntervalNow();
            }

retry:
            ready = select(maxfd + 1, rdp, wrp, exp, tvp);
            if (-1 == ready)
            {
                PRIntn oserror = errno;

                if ((EINTR == oserror) || (EAGAIN == oserror))
                {
                    if (timeout == PR_INTERVAL_NO_TIMEOUT)
                        goto retry;
                    else if (timeout == PR_INTERVAL_NO_WAIT)
                        ready = 0;  /* don't retry, just time out */
                    else
                    {
                        elapsed = (PRIntervalTime) (PR_IntervalNow()
                                - start);
                        if (elapsed > timeout)
                            ready = 0;  /* timed out */
                        else
                        {
                            remaining = timeout - elapsed;
                            msecs = PR_IntervalToMilliseconds(remaining);
							tv.tv_sec = msecs/PR_MSEC_PER_SEC;
							tv.tv_usec = (msecs % PR_MSEC_PER_SEC) *
													PR_USEC_PER_MSEC;
                            goto retry;
                        }
                    }
                } else if (EBADF == oserror)
                {
					/* find all the bad fds */
					ready = 0;
                	for (index = 0; index < npds; ++index)
					{
                    	pds[index].out_flags = 0;
            			if ((NULL != pds[index].fd) &&
											(0 != pds[index].in_flags))
						{
							if (fcntl(selectfd[index], F_GETFL, 0) == -1)
							{
                    			pds[index].out_flags = PR_POLL_NVAL;
								ready++;
							}
						}
					}
                } else 
                    _PR_MD_MAP_SELECT_ERROR(oserror);
            }
            else if (ready > 0)
            {
                for (index = 0; index < npds; ++index)
                {
                    PRInt16 out_flags = 0;
                    if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
                    {
						if (FD_ISSET(selectfd[index], &rd))
						{
							if (pds[index].out_flags
							& _PR_POLL_READ_SYS_READ)
							{
								out_flags |= PR_POLL_READ;
							}
							if (pds[index].out_flags
							& _PR_POLL_WRITE_SYS_READ)
							{
								out_flags |= PR_POLL_WRITE;
							}
						}
						if (FD_ISSET(selectfd[index], &wr))
						{
							if (pds[index].out_flags
							& _PR_POLL_READ_SYS_WRITE)
							{
								out_flags |= PR_POLL_READ;
							}
							if (pds[index].out_flags
							& _PR_POLL_WRITE_SYS_WRITE)
							{
								out_flags |= PR_POLL_WRITE;
							}
						}
						if (FD_ISSET(selectfd[index], &ex))
							out_flags |= PR_POLL_EXCEPT;
                    }
                    pds[index].out_flags = out_flags;
                }
            }
        }
    }
    return ready;

} /* _pr_poll_with_select */
#endif	/* _PR_POLL_WITH_SELECT */

PR_IMPLEMENT(PRInt32) PR_Poll(
    PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
#if defined(_PR_POLL_WITH_SELECT)
	return(_pr_poll_with_select(pds, npds, timeout));
#else
	return(_pr_poll_with_poll(pds, npds, timeout));
#endif
}

PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags)
{
    struct dirent *dp;

    if (pt_TestAbort()) return NULL;

    for (;;)
    {
        errno = 0;
        dp = readdir(dir->md.d);
        if (NULL == dp)
        {
            pt_MapError(_PR_MD_MAP_READDIR_ERROR, errno);
            return NULL;
        }
        if ((flags & PR_SKIP_DOT)
            && ('.' == dp->d_name[0])
            && (0 == dp->d_name[1])) continue;
        if ((flags & PR_SKIP_DOT_DOT)
            && ('.' == dp->d_name[0])
            && ('.' == dp->d_name[1])
            && (0 == dp->d_name[2])) continue;
        if ((flags & PR_SKIP_HIDDEN) && ('.' == dp->d_name[0]))
            continue;
        break;
    }
    dir->d.name = dp->d_name;
    return &dir->d;
}  /* PR_ReadDir */

PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void)
{
    PRIntn domain = PF_INET;

    return PR_Socket(domain, SOCK_DGRAM, 0);
}  /* PR_NewUDPSocket */

PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket(void)
{
    PRIntn domain = PF_INET;

    return PR_Socket(domain, SOCK_STREAM, 0);
}  /* PR_NewTCPSocket */

PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af)
{
    return PR_Socket(af, SOCK_DGRAM, 0);
}  /* PR_NewUDPSocket */

PR_IMPLEMENT(PRFileDesc*) PR_OpenTCPSocket(PRIntn af)
{
    return PR_Socket(af, SOCK_STREAM, 0);
}  /* PR_NewTCPSocket */

PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *fds[2])
{
#ifdef SYMBIAN
    /*
     * For the platforms that don't have socketpair.
     *
     * Copied from prsocket.c, with the parameter f[] renamed fds[] and the
     * _PR_CONNECT_DOES_NOT_BIND code removed.
     */
    PRFileDesc *listenSock;
    PRNetAddr selfAddr, peerAddr;
    PRUint16 port;

    fds[0] = fds[1] = NULL;
    listenSock = PR_NewTCPSocket();
    if (listenSock == NULL) {
        goto failed;
    }
    PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */
    if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) {
        goto failed;
    }
    if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) {
        goto failed;
    }
    port = ntohs(selfAddr.inet.port);
    if (PR_Listen(listenSock, 5) == PR_FAILURE) {
        goto failed;
    }
    fds[0] = PR_NewTCPSocket();
    if (fds[0] == NULL) {
        goto failed;
    }
    PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr);

    /*
     * Only a thread is used to do the connect and accept.
     * I am relying on the fact that PR_Connect returns
     * successfully as soon as the connect request is put
     * into the listen queue (but before PR_Accept is called).
     * This is the behavior of the BSD socket code.  If
     * connect does not return until accept is called, we
     * will need to create another thread to call connect.
     */
    if (PR_Connect(fds[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT)
            == PR_FAILURE) {
        goto failed;
    }
    /*
     * A malicious local process may connect to the listening
     * socket, so we need to verify that the accepted connection
     * is made from our own socket fds[0].
     */
    if (PR_GetSockName(fds[0], &selfAddr) == PR_FAILURE) {
        goto failed;
    }
    fds[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT);
    if (fds[1] == NULL) {
        goto failed;
    }
    if (peerAddr.inet.port != selfAddr.inet.port) {
        /* the connection we accepted is not from fds[0] */
        PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
        goto failed;
    }
    PR_Close(listenSock);
    return PR_SUCCESS;

failed:
    if (listenSock) {
        PR_Close(listenSock);
    }
    if (fds[0]) {
        PR_Close(fds[0]);
    }
    if (fds[1]) {
        PR_Close(fds[1]);
    }
    return PR_FAILURE;
#else
    PRInt32 osfd[2];

    if (pt_TestAbort()) return PR_FAILURE;

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, osfd) == -1) {
        pt_MapError(_PR_MD_MAP_SOCKETPAIR_ERROR, errno);
        return PR_FAILURE;
    }

    fds[0] = pt_SetMethods(osfd[0], PR_DESC_SOCKET_TCP, PR_FALSE, PR_FALSE);
    if (fds[0] == NULL) {
        close(osfd[0]);
        close(osfd[1]);
        return PR_FAILURE;
    }
    fds[1] = pt_SetMethods(osfd[1], PR_DESC_SOCKET_TCP, PR_FALSE, PR_FALSE);
    if (fds[1] == NULL) {
        PR_Close(fds[0]);
        close(osfd[1]);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
#endif
}  /* PR_NewTCPSocketPair */

PR_IMPLEMENT(PRStatus) PR_CreatePipe(
    PRFileDesc **readPipe,
    PRFileDesc **writePipe
)
{
    int pipefd[2];

    if (pt_TestAbort()) return PR_FAILURE;

    if (pipe(pipefd) == -1)
    {
    /* XXX map pipe error */
        PR_SetError(PR_UNKNOWN_ERROR, errno);
        return PR_FAILURE;
    }
    *readPipe = pt_SetMethods(pipefd[0], PR_DESC_PIPE, PR_FALSE, PR_FALSE);
    if (NULL == *readPipe)
    {
        close(pipefd[0]);
        close(pipefd[1]);
        return PR_FAILURE;
    }
    *writePipe = pt_SetMethods(pipefd[1], PR_DESC_PIPE, PR_FALSE, PR_FALSE);
    if (NULL == *writePipe)
    {
        PR_Close(*readPipe);
        close(pipefd[1]);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}

/*
** Set the inheritance attribute of a file descriptor.
*/
PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(
    PRFileDesc *fd,
    PRBool inheritable)
{
    /*
     * Only a non-layered, NSPR file descriptor can be inherited
     * by a child process.
     */
    if (fd->identity != PR_NSPR_IO_LAYER)
    {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        return PR_FAILURE;
    }
    if (fd->secret->inheritable != inheritable)
    {
        if (fcntl(fd->secret->md.osfd, F_SETFD,
        inheritable ? 0 : FD_CLOEXEC) == -1)
        {
            _PR_MD_MAP_DEFAULT_ERROR(errno);
            return PR_FAILURE;
        }
        fd->secret->inheritable = (_PRTriStateBool) inheritable;
    }
    return PR_SUCCESS;
}

/*****************************************************************************/
/***************************** I/O friends methods ***************************/
/*****************************************************************************/

PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd)
{
    PRFileDesc *fd;

    if (!_pr_initialized) _PR_ImplicitInitialization();
    fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE, PR_TRUE);
    if (NULL == fd) close(osfd);
    return fd;
}  /* PR_ImportFile */

PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PRInt32 osfd)
{
    PRFileDesc *fd;

    if (!_pr_initialized) _PR_ImplicitInitialization();
    fd = pt_SetMethods(osfd, PR_DESC_PIPE, PR_FALSE, PR_TRUE);
    if (NULL == fd) close(osfd);
    return fd;
}  /* PR_ImportPipe */

PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd)
{
    PRFileDesc *fd;

    if (!_pr_initialized) _PR_ImplicitInitialization();
    fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE, PR_TRUE);
    if (NULL == fd) close(osfd);
#ifdef _PR_NEED_SECRET_AF
    if (NULL != fd) fd->secret->af = PF_INET;
#endif
    return fd;
}  /* PR_ImportTCPSocket */

PR_IMPLEMENT(PRFileDesc*) PR_ImportUDPSocket(PRInt32 osfd)
{
    PRFileDesc *fd;

    if (!_pr_initialized) _PR_ImplicitInitialization();
    fd = pt_SetMethods(osfd, PR_DESC_SOCKET_UDP, PR_FALSE, PR_TRUE);
    if (NULL != fd) close(osfd);
    return fd;
}  /* PR_ImportUDPSocket */

PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PRInt32 osfd)
{
    PRFileDesc *fd;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    fd = _PR_Getfd();

    if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    else
    {
        fd->secret->md.osfd = osfd;
        fd->secret->inheritable = _PR_TRI_FALSE;
    	fd->secret->state = _PR_FILEDESC_OPEN;
        fd->methods = PR_GetSocketPollFdMethods();
    }

    return fd;
}  /* PR_CreateSocketPollFD */

PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd)
{
    if (NULL == fd)
    {
        PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
        return PR_FAILURE;
    }
    fd->secret->state = _PR_FILEDESC_CLOSED;
    _PR_Putfd(fd);
    return PR_SUCCESS;
}  /* PR_DestroySocketPollFd */

PR_IMPLEMENT(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *bottom)
{
    PRInt32 osfd = -1;
    bottom = (NULL == bottom) ?
        NULL : PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER);
    if (NULL == bottom) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    else osfd = bottom->secret->md.osfd;
    return osfd;
}  /* PR_FileDesc2NativeHandle */

PR_IMPLEMENT(void) PR_ChangeFileDescNativeHandle(PRFileDesc *fd,
    PRInt32 handle)
{
    if (fd) fd->secret->md.osfd = handle;
}  /*  PR_ChangeFileDescNativeHandle*/

PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
{
    PRStatus status = PR_SUCCESS;

    if (pt_TestAbort()) return PR_FAILURE;

    PR_Lock(_pr_flock_lock);
    while (-1 == fd->secret->lockCount)
        PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT);
    if (0 == fd->secret->lockCount)
    {
        fd->secret->lockCount = -1;
        PR_Unlock(_pr_flock_lock);
        status = _PR_MD_LOCKFILE(fd->secret->md.osfd);
        PR_Lock(_pr_flock_lock);
        fd->secret->lockCount = (PR_SUCCESS == status) ? 1 : 0;
        PR_NotifyAllCondVar(_pr_flock_cv);
    }
    else
    {
        fd->secret->lockCount += 1;
    }
    PR_Unlock(_pr_flock_lock);
 
    return status;
}  /* PR_LockFile */

PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)
{
    PRStatus status = PR_SUCCESS;

    if (pt_TestAbort()) return PR_FAILURE;

    PR_Lock(_pr_flock_lock);
    if (0 == fd->secret->lockCount)
    {
        status = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
        if (PR_SUCCESS == status) fd->secret->lockCount = 1;
    }
    else fd->secret->lockCount += 1;
    PR_Unlock(_pr_flock_lock);
 
    return status;
}  /* PR_TLockFile */

PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)
{
    PRStatus status = PR_SUCCESS;

    if (pt_TestAbort()) return PR_FAILURE;

    PR_Lock(_pr_flock_lock);
    if (fd->secret->lockCount == 1)
    {
        status = _PR_MD_UNLOCKFILE(fd->secret->md.osfd);
        if (PR_SUCCESS == status) fd->secret->lockCount = 0;
    }
    else fd->secret->lockCount -= 1;
    PR_Unlock(_pr_flock_lock);

    return status;
}

/*
 * The next two entry points should not be in the API, but they are
 * defined here for historical (or hysterical) reasons.
 */

PR_IMPLEMENT(PRInt32) PR_GetSysfdTableMax(void)
{
#if defined(AIX) || defined(SYMBIAN)
    return sysconf(_SC_OPEN_MAX);
#else
    struct rlimit rlim;

    if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) 
       return -1;

    return rlim.rlim_max;
#endif
}

PR_IMPLEMENT(PRInt32) PR_SetSysfdTableSize(PRIntn table_size)
{
#if defined(AIX) || defined(SYMBIAN)
    return -1;
#else
    struct rlimit rlim;
    PRInt32 tableMax = PR_GetSysfdTableMax();

    if (tableMax < 0) return -1;
    rlim.rlim_max = tableMax;

    /* Grow as much as we can; even if too big */
    if ( rlim.rlim_max < table_size )
        rlim.rlim_cur = rlim.rlim_max;
    else
        rlim.rlim_cur = table_size;

    if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) 
        return -1;

    return rlim.rlim_cur;
#endif
}

/*
 * PR_Stat is supported for backward compatibility; some existing Java
 * code uses it.  New code should use PR_GetFileInfo.
 */

#ifndef NO_NSPR_10_SUPPORT
PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
{
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_Stat", "PR_GetFileInfo");

    if (pt_TestAbort()) return -1;

    if (-1 == stat(name, buf)) {
        pt_MapError(_PR_MD_MAP_STAT_ERROR, errno);
        return -1;
    } else {
        return 0;
    }
}
#endif /* ! NO_NSPR_10_SUPPORT */


PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set)
{
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_FD_ZERO (PR_Select)", "PR_Poll");
    memset(set, 0, sizeof(PR_fd_set));
}

PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set)
{
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_FD_SET (PR_Select)", "PR_Poll");
    PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC );

    set->harray[set->hsize++] = fh;
}

PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set)
{
    PRUint32 index, index2;
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_FD_CLR (PR_Select)", "PR_Poll");

    for (index = 0; index<set->hsize; index++)
       if (set->harray[index] == fh) {
           for (index2=index; index2 < (set->hsize-1); index2++) {
               set->harray[index2] = set->harray[index2+1];
           }
           set->hsize--;
           break;
       }
}

PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set)
{
    PRUint32 index;
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_FD_ISSET (PR_Select)", "PR_Poll");
    for (index = 0; index<set->hsize; index++)
       if (set->harray[index] == fh) {
           return 1;
       }
    return 0;
}

PR_IMPLEMENT(void) PR_FD_NSET(PRInt32 fd, PR_fd_set *set)
{
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_FD_NSET (PR_Select)", "PR_Poll");
    PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC );

    set->narray[set->nsize++] = fd;
}

PR_IMPLEMENT(void) PR_FD_NCLR(PRInt32 fd, PR_fd_set *set)
{
    PRUint32 index, index2;
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_FD_NCLR (PR_Select)", "PR_Poll");

    for (index = 0; index<set->nsize; index++)
       if (set->narray[index] == fd) {
           for (index2=index; index2 < (set->nsize-1); index2++) {
               set->narray[index2] = set->narray[index2+1];
           }
           set->nsize--;
           break;
       }
}

PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PRInt32 fd, PR_fd_set *set)
{
    PRUint32 index;
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete("PR_FD_NISSET (PR_Select)", "PR_Poll");
    for (index = 0; index<set->nsize; index++)
       if (set->narray[index] == fd) {
           return 1;
       }
    return 0;
}

#include <sys/types.h>
#include <sys/time.h>
#if !defined(SUNOS4) && !defined(HPUX) \
    && !defined(LINUX) && !defined(__GNU__) && !defined(__GLIBC__)
#include <sys/select.h>
#endif

static PRInt32
_PR_getset(PR_fd_set *pr_set, fd_set *set)
{
    PRUint32 index;
    PRInt32 max = 0;

    if (!pr_set)
        return 0;
   
    FD_ZERO(set);

    /* First set the pr file handle osfds */
    for (index=0; index<pr_set->hsize; index++) {
        FD_SET(pr_set->harray[index]->secret->md.osfd, set);
        if (pr_set->harray[index]->secret->md.osfd > max)
            max = pr_set->harray[index]->secret->md.osfd;
    }
    /* Second set the native osfds */
    for (index=0; index<pr_set->nsize; index++) {
        FD_SET(pr_set->narray[index], set);
        if (pr_set->narray[index] > max)
            max = pr_set->narray[index];
    }
    return max;
}

static void
_PR_setset(PR_fd_set *pr_set, fd_set *set)
{
    PRUint32 index, last_used;

    if (!pr_set)
        return;

    for (last_used=0, index=0; index<pr_set->hsize; index++) {
        if ( FD_ISSET(pr_set->harray[index]->secret->md.osfd, set) ) {
            pr_set->harray[last_used++] = pr_set->harray[index];
        }
    }
    pr_set->hsize = last_used;

    for (last_used=0, index=0; index<pr_set->nsize; index++) {
        if ( FD_ISSET(pr_set->narray[index], set) ) {
            pr_set->narray[last_used++] = pr_set->narray[index];
        }
    }
    pr_set->nsize = last_used;
}

PR_IMPLEMENT(PRInt32) PR_Select(
    PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr, 
    PR_fd_set *pr_ex, PRIntervalTime timeout)
{
    fd_set rd, wr, ex;
    struct timeval tv, *tvp;
    PRInt32 max, max_fd;
    PRInt32 rv;
    /*
     * For restarting select() if it is interrupted by a Unix signal.
     * We use these variables to figure out how much time has elapsed
     * and how much of the timeout still remains.
     */
    PRIntervalTime start, elapsed, remaining;

    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete( "PR_Select", "PR_Poll");

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&ex);

    max_fd = _PR_getset(pr_rd, &rd);
    max_fd = (max = _PR_getset(pr_wr, &wr))>max_fd?max:max_fd;
    max_fd = (max = _PR_getset(pr_ex, &ex))>max_fd?max:max_fd;

    if (timeout == PR_INTERVAL_NO_TIMEOUT) {
        tvp = NULL;
    } else {
        tv.tv_sec = (PRInt32)PR_IntervalToSeconds(timeout);
        tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds(
                timeout - PR_SecondsToInterval(tv.tv_sec));
        tvp = &tv;
        start = PR_IntervalNow();
    }

retry:
    rv = select(max_fd + 1, (_PRSelectFdSetArg_t) &rd,
        (_PRSelectFdSetArg_t) &wr, (_PRSelectFdSetArg_t) &ex, tvp);

    if (rv == -1 && errno == EINTR) {
        if (timeout == PR_INTERVAL_NO_TIMEOUT) {
            goto retry;
        } else {
            elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
            if (elapsed > timeout) {
                rv = 0;  /* timed out */
            } else {
                remaining = timeout - elapsed;
                tv.tv_sec = (PRInt32)PR_IntervalToSeconds(remaining);
                tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds(
                        remaining - PR_SecondsToInterval(tv.tv_sec));
                goto retry;
            }
        }
    }

    if (rv > 0) {
        _PR_setset(pr_rd, &rd);
        _PR_setset(pr_wr, &wr);
        _PR_setset(pr_ex, &ex);
    } else if (rv == -1) {
        pt_MapError(_PR_MD_MAP_SELECT_ERROR, errno);
    }
    return rv;
}
#endif /* defined(_PR_PTHREADS) */

#ifdef MOZ_UNICODE 
/* ================ UTF16 Interfaces ================================ */
PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16(
    const PRUnichar *name, PRIntn flags, PRIntn mode)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return NULL;
}

PR_IMPLEMENT(PRStatus) PR_CloseDirUTF16(PRDir *dir)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
}

PR_IMPLEMENT(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return NULL;
}

PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return NULL;
}

PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
}
/* ================ UTF16 Interfaces ================================ */
#endif /* MOZ_UNICODE */

/* ptio.c */

deps/mozilla/nsprpub/pr/src/pthreads/ptmisc.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
** File:   ptmisc.c
** Descritpion:  Implemenation of miscellaneous methods for pthreads
*/

#if defined(_PR_PTHREADS)

#include "primpl.h"

#include <stdio.h>
#ifdef SOLARIS
#include <thread.h>
#endif

#define PT_LOG(f)

void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")}
void _PR_InitStacks(void) {PT_LOG("_PR_InitStacks")}

PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs) 
{
#ifdef SOLARIS
	thr_setconcurrency(numCPUs);	
#else
	PT_LOG("PR_SetConcurrency");
#endif
}

PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 flag)
    {PT_LOG("PR_SetThreadRecycleMode")}

#endif /* defined(_PR_PTHREADS) */

/* ptmisc.c */

deps/mozilla/nsprpub/pr/src/pthreads/ptsynch.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
** File:            ptsynch.c
** Descritpion:        Implemenation for thread synchronization using pthreads
** Exports:            prlock.h, prcvar.h, prmon.h, prcmon.h
*/

#if defined(_PR_PTHREADS)

#include "primpl.h"
#include "obsolete/prsem.h"

#include <string.h>
#include <pthread.h>
#include <sys/time.h>

static pthread_mutexattr_t _pt_mattr;
static pthread_condattr_t _pt_cvar_attr;

#if defined(DEBUG)
extern PTDebug pt_debug;  /* this is shared between several modules */

#if defined(_PR_DCETHREADS)
static pthread_t pt_zero_tid;  /* a null pthread_t (pthread_t is a struct
                                * in DCE threads) to compare with */
#endif  /* defined(_PR_DCETHREADS) */
#endif  /* defined(DEBUG) */

#if defined(FREEBSD)
/*
 * On older versions of FreeBSD, pthread_mutex_trylock returns EDEADLK.
 * Newer versions return EBUSY.  We still need to support both.
 */
static int
pt_pthread_mutex_is_locked(pthread_mutex_t *m)
{
    int rv = pthread_mutex_trylock(m);
    return (EBUSY == rv || EDEADLK == rv);
}
#endif

/**************************************************************/
/**************************************************************/
/*****************************LOCKS****************************/
/**************************************************************/
/**************************************************************/

void _PR_InitLocks(void)
{
    int rv;
    rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr); 
    PR_ASSERT(0 == rv);

#ifdef LINUX
#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
    rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
    PR_ASSERT(0 == rv);
#endif
#endif

    rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
    PR_ASSERT(0 == rv);
}

static void pt_PostNotifies(PRLock *lock, PRBool unlock)
{
    PRIntn index, rv;
    _PT_Notified post;
    _PT_Notified *notified, *prev = NULL;
    /*
     * Time to actually notify any conditions that were affected
     * while the lock was held. Get a copy of the list that's in
     * the lock structure and then zero the original. If it's
     * linked to other such structures, we own that storage.
     */
    post = lock->notified;  /* a safe copy; we own the lock */

#if defined(DEBUG)
    memset(&lock->notified, 0, sizeof(_PT_Notified));  /* reset */
#else
    lock->notified.length = 0;  /* these are really sufficient */
    lock->notified.link = NULL;
#endif

    /* should (may) we release lock before notifying? */
    if (unlock)
    {
        rv = pthread_mutex_unlock(&lock->mutex);
        PR_ASSERT(0 == rv);
    }

    notified = &post;  /* this is where we start */
    do
    {
        for (index = 0; index < notified->length; ++index)
        {
            PRCondVar *cv = notified->cv[index].cv;
            PR_ASSERT(NULL != cv);
            PR_ASSERT(0 != notified->cv[index].times);
            if (-1 == notified->cv[index].times)
            {
                rv = pthread_cond_broadcast(&cv->cv);
                PR_ASSERT(0 == rv);
            }
            else
            {
                while (notified->cv[index].times-- > 0)
                {
                    rv = pthread_cond_signal(&cv->cv);
                    PR_ASSERT(0 == rv);
                }
            }
#if defined(DEBUG)
            pt_debug.cvars_notified += 1;
            if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
            {
                pt_debug.delayed_cv_deletes += 1;
                PR_DestroyCondVar(cv);
            }
#else  /* defined(DEBUG) */
            if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
                PR_DestroyCondVar(cv);
#endif  /* defined(DEBUG) */
        }
        prev = notified;
        notified = notified->link;
        if (&post != prev) PR_DELETE(prev);
    } while (NULL != notified);
}  /* pt_PostNotifies */

PR_IMPLEMENT(PRLock*) PR_NewLock(void)
{
    PRIntn rv;
    PRLock *lock;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    lock = PR_NEWZAP(PRLock);
    if (lock != NULL)
    {
        rv = _PT_PTHREAD_MUTEX_INIT(lock->mutex, _pt_mattr); 
        PR_ASSERT(0 == rv);
    }
#if defined(DEBUG)
    pt_debug.locks_created += 1;
#endif
    return lock;
}  /* PR_NewLock */

PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
{
    PRIntn rv;
    PR_ASSERT(NULL != lock);
    PR_ASSERT(PR_FALSE == lock->locked);
    PR_ASSERT(0 == lock->notified.length);
    PR_ASSERT(NULL == lock->notified.link);
    rv = pthread_mutex_destroy(&lock->mutex);
    PR_ASSERT(0 == rv);
#if defined(DEBUG)
    memset(lock, 0xaf, sizeof(PRLock));
    pt_debug.locks_destroyed += 1;
#endif
    PR_Free(lock);
}  /* PR_DestroyLock */

PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
{
    PRIntn rv;
    PR_ASSERT(lock != NULL);
    rv = pthread_mutex_lock(&lock->mutex);
    PR_ASSERT(0 == rv);
    PR_ASSERT(0 == lock->notified.length);
    PR_ASSERT(NULL == lock->notified.link);
    PR_ASSERT(PR_FALSE == lock->locked);
    /* Nb: the order of the next two statements is not critical to
     * the correctness of PR_AssertCurrentThreadOwnsLock(), but 
     * this particular order makes the assertion more likely to
     * catch errors. */
    lock->owner = pthread_self();
    lock->locked = PR_TRUE;
#if defined(DEBUG)
    pt_debug.locks_acquired += 1;
#endif
}  /* PR_Lock */

PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
{
    PRIntn rv;

    PR_ASSERT(lock != NULL);
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
    PR_ASSERT(PR_TRUE == lock->locked);
    PR_ASSERT(pthread_equal(lock->owner, pthread_self()));

    if (!lock->locked || !pthread_equal(lock->owner, pthread_self()))
        return PR_FAILURE;

    lock->locked = PR_FALSE;
    if (0 == lock->notified.length)  /* shortcut */
    {
        rv = pthread_mutex_unlock(&lock->mutex);
        PR_ASSERT(0 == rv);
    }
    else pt_PostNotifies(lock, PR_TRUE);

#if defined(DEBUG)
    pt_debug.locks_released += 1;
#endif
    return PR_SUCCESS;
}  /* PR_Unlock */

PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock)
{
    /* Nb: the order of the |locked| and |owner==me| checks is not critical 
     * to the correctness of PR_AssertCurrentThreadOwnsLock(), but 
     * this particular order makes the assertion more likely to
     * catch errors. */
    PR_ASSERT(lock->locked && pthread_equal(lock->owner, pthread_self()));
}

/**************************************************************/
/**************************************************************/
/***************************CONDITIONS*************************/
/**************************************************************/
/**************************************************************/


/*
 * This code is used to compute the absolute time for the wakeup.
 * It's moderately ugly, so it's defined here and called in a
 * couple of places.
 */
#define PT_NANOPERMICRO 1000UL
#define PT_BILLION 1000000000UL

static PRIntn pt_TimedWait(
    pthread_cond_t *cv, pthread_mutex_t *ml, PRIntervalTime timeout)
{
    int rv;
    struct timeval now;
    struct timespec tmo;
    PRUint32 ticks = PR_TicksPerSecond();

    tmo.tv_sec = (PRInt32)(timeout / ticks);
    tmo.tv_nsec = (PRInt32)(timeout - (tmo.tv_sec * ticks));
    tmo.tv_nsec = (PRInt32)PR_IntervalToMicroseconds(PT_NANOPERMICRO * tmo.tv_nsec);

    /* pthreads wants this in absolute time, off we go ... */
    (void)GETTIMEOFDAY(&now);
    /* that one's usecs, this one's nsecs - grrrr! */
    tmo.tv_sec += now.tv_sec;
    tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);
    tmo.tv_sec += tmo.tv_nsec / PT_BILLION;
    tmo.tv_nsec %= PT_BILLION;

    rv = pthread_cond_timedwait(cv, ml, &tmo);

    /* NSPR doesn't report timeouts */
#ifdef _PR_DCETHREADS
    if (rv == -1) return (errno == EAGAIN) ? 0 : errno;
    else return rv;
#else
    return (rv == ETIMEDOUT) ? 0 : rv;
#endif
}  /* pt_TimedWait */


/*
 * Notifies just get posted to the protecting mutex. The
 * actual notification is done when the lock is released so that
 * MP systems don't contend for a lock that they can't have.
 */
static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool broadcast)
{
    PRIntn index = 0;
    _PT_Notified *notified = &cvar->lock->notified;

    PR_ASSERT(PR_TRUE == cvar->lock->locked);
    PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));

    while (1)
    {
        for (index = 0; index < notified->length; ++index)
        {
            if (notified->cv[index].cv == cvar)
            {
                if (broadcast)
                    notified->cv[index].times = -1;
                else if (-1 != notified->cv[index].times)
                    notified->cv[index].times += 1;
                goto finished;  /* we're finished */
            }
        }
        /* if not full, enter new CV in this array */
        if (notified->length < PT_CV_NOTIFIED_LENGTH) break;

        /* if there's no link, create an empty array and link it */
        if (NULL == notified->link)
            notified->link = PR_NEWZAP(_PT_Notified);
        notified = notified->link;
    }

    /* A brand new entry in the array */
    (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending);
    notified->cv[index].times = (broadcast) ? -1 : 1;
    notified->cv[index].cv = cvar;
    notified->length += 1;

finished:
    PR_ASSERT(PR_TRUE == cvar->lock->locked);
    PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
}  /* pt_PostNotifyToCvar */

PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
{
    PRCondVar *cv = PR_NEW(PRCondVar);
    PR_ASSERT(lock != NULL);
    if (cv != NULL)
    {
        int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); 
        PR_ASSERT(0 == rv);
        cv->lock = lock;
        cv->notify_pending = 0;
#if defined(DEBUG)
        pt_debug.cvars_created += 1;
#endif
    }
    return cv;
}  /* PR_NewCondVar */

PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
{
    if (0 > PR_ATOMIC_DECREMENT(&cvar->notify_pending))
    {
        PRIntn rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
#if defined(DEBUG)
        memset(cvar, 0xaf, sizeof(PRCondVar));
        pt_debug.cvars_destroyed += 1;
#endif
        PR_Free(cvar);
    }
}  /* PR_DestroyCondVar */

PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
{
    PRIntn rv;
    PRThread *thred = PR_GetCurrentThread();

    PR_ASSERT(cvar != NULL);
    /* We'd better be locked */
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
    PR_ASSERT(PR_TRUE == cvar->lock->locked);
    /* and it better be by us */
    PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));

    if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;

    /*
     * The thread waiting is used for PR_Interrupt
     */
    thred->waiting = cvar;  /* this is where we're waiting */

    /*
     * If we have pending notifies, post them now.
     *
     * This is not optimal. We're going to post these notifies
     * while we're holding the lock. That means on MP systems
     * that they are going to collide for the lock that we will
     * hold until we actually wait.
     */
    if (0 != cvar->lock->notified.length)
        pt_PostNotifies(cvar->lock, PR_FALSE);

    /*
     * We're surrendering the lock, so clear out the locked field.
     */
    cvar->lock->locked = PR_FALSE;

    if (timeout == PR_INTERVAL_NO_TIMEOUT)
        rv = pthread_cond_wait(&cvar->cv, &cvar->lock->mutex);
    else
        rv = pt_TimedWait(&cvar->cv, &cvar->lock->mutex, timeout);

    /* We just got the lock back - this better be empty */
    PR_ASSERT(PR_FALSE == cvar->lock->locked);
    cvar->lock->locked = PR_TRUE;
    cvar->lock->owner = pthread_self();

    PR_ASSERT(0 == cvar->lock->notified.length);
    thred->waiting = NULL;  /* and now we're not */
    if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
    if (rv != 0)
    {
        _PR_MD_MAP_DEFAULT_ERROR(rv);
        return PR_FAILURE;
    }
    return PR_SUCCESS;

aborted:
    PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
    thred->state &= ~PT_THREAD_ABORTED;
    return PR_FAILURE;
}  /* PR_WaitCondVar */

PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
{
    PR_ASSERT(cvar != NULL);   
    pt_PostNotifyToCvar(cvar, PR_FALSE);
    return PR_SUCCESS;
}  /* PR_NotifyCondVar */

PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
{
    PR_ASSERT(cvar != NULL);
    pt_PostNotifyToCvar(cvar, PR_TRUE);
    return PR_SUCCESS;
}  /* PR_NotifyAllCondVar */

/**************************************************************/
/**************************************************************/
/***************************MONITORS***************************/
/**************************************************************/
/**************************************************************/

PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
{
    PRMonitor *mon;
    PRCondVar *cvar;
    int rv;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    cvar = PR_NEWZAP(PRCondVar);
    if (NULL == cvar)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }
    mon = PR_NEWZAP(PRMonitor);
    if (mon == NULL)
    {
        PR_Free(cvar);
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }

    rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr); 
    PR_ASSERT(0 == rv);
    if (0 != rv)
    {
        PR_Free(mon);
        PR_Free(cvar);
        PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
        return NULL;
    }

    _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);

    mon->cvar = cvar;
    rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr); 
    PR_ASSERT(0 == rv);
    mon->entryCount = 0;
    mon->cvar->lock = &mon->lock;
    if (0 != rv)
    {
        pthread_mutex_destroy(&mon->lock.mutex);
        PR_Free(mon);
        PR_Free(cvar);
        PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
        return NULL;
    }
    return mon;
}  /* PR_NewMonitor */

PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
{
    PRMonitor* mon = PR_NewMonitor();
    if (mon)
        mon->name = name;
    return mon;
}

PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
{
    int rv;
    PR_ASSERT(mon != NULL);
    PR_DestroyCondVar(mon->cvar);
    rv = pthread_mutex_destroy(&mon->lock.mutex); PR_ASSERT(0 == rv);
#if defined(DEBUG)
        memset(mon, 0xaf, sizeof(PRMonitor));
#endif
    PR_Free(mon);    
}  /* PR_DestroyMonitor */


/* The GC uses this; it is quite arguably a bad interface.  I'm just 
 * duplicating it for now - XXXMB
 */
PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
{
    pthread_t self = pthread_self();
    if (pthread_equal(mon->owner, self))
        return mon->entryCount;
    return 0;
}

PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
{
    PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(&mon->lock);
}

PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
{
    pthread_t self = pthread_self();

    PR_ASSERT(mon != NULL);
    /*
     * This is safe only if mon->owner (a pthread_t) can be
     * read in one instruction.  Perhaps mon->owner should be
     * a "PRThread *"?
     */
    if (!pthread_equal(mon->owner, self))
    {
        PR_Lock(&mon->lock);
        /* and now I have the lock */
        PR_ASSERT(0 == mon->entryCount);
        PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
        _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
    }
    mon->entryCount += 1;
}  /* PR_EnterMonitor */

PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
{
    pthread_t self = pthread_self();

    PR_ASSERT(mon != NULL);
    /* The lock better be that - locked */
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
    /* we'd better be the owner */
    PR_ASSERT(pthread_equal(mon->owner, self));
    if (!pthread_equal(mon->owner, self))
        return PR_FAILURE;

    /* if it's locked and we have it, then the entries should be > 0 */
    PR_ASSERT(mon->entryCount > 0);
    mon->entryCount -= 1;  /* reduce by one */
    if (mon->entryCount == 0)
    {
        /* and if it transitioned to zero - unlock */
        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);  /* make the owner unknown */
        PR_Unlock(&mon->lock);
    }
    return PR_SUCCESS;
}  /* PR_ExitMonitor */

PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
{
    PRStatus rv;
    PRInt16 saved_entries;
    pthread_t saved_owner;

    PR_ASSERT(mon != NULL);
    /* we'd better be locked */
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
    /* and the entries better be positive */
    PR_ASSERT(mon->entryCount > 0);
    /* and it better be by us */
    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));

    /* tuck these away 'till later */
    saved_entries = mon->entryCount; 
    mon->entryCount = 0;
    _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
    _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
    
    rv = PR_WaitCondVar(mon->cvar, timeout);

    /* reinstate the intresting information */
    mon->entryCount = saved_entries;
    _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);

    return rv;
}  /* PR_Wait */

PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
{
    PR_ASSERT(NULL != mon);
    /* we'd better be locked */
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
    /* and the entries better be positive */
    PR_ASSERT(mon->entryCount > 0);
    /* and it better be by us */
    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));

    pt_PostNotifyToCvar(mon->cvar, PR_FALSE);

    return PR_SUCCESS;
}  /* PR_Notify */

PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
{
    PR_ASSERT(mon != NULL);
    /* we'd better be locked */
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
    /* and the entries better be positive */
    PR_ASSERT(mon->entryCount > 0);
    /* and it better be by us */
    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));

    pt_PostNotifyToCvar(mon->cvar, PR_TRUE);

    return PR_SUCCESS;
}  /* PR_NotifyAll */

/**************************************************************/
/**************************************************************/
/**************************SEMAPHORES**************************/
/**************************************************************/
/**************************************************************/
PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore)
{
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete(
        "PR_PostSem", "locks & condition variables");
	PR_Lock(semaphore->cvar->lock);
	PR_NotifyCondVar(semaphore->cvar);
	semaphore->count += 1;
	PR_Unlock(semaphore->cvar->lock);
}  /* PR_PostSem */

PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *semaphore)
{
	PRStatus status = PR_SUCCESS;
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete(
        "PR_WaitSem", "locks & condition variables");
	PR_Lock(semaphore->cvar->lock);
	while ((semaphore->count == 0) && (PR_SUCCESS == status))
		status = PR_WaitCondVar(semaphore->cvar, PR_INTERVAL_NO_TIMEOUT);
	if (PR_SUCCESS == status) semaphore->count -= 1;
	PR_Unlock(semaphore->cvar->lock);
	return status;
}  /* PR_WaitSem */

PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *semaphore)
{
    static PRBool unwarned = PR_TRUE;
    if (unwarned) unwarned = _PR_Obsolete(
        "PR_DestroySem", "locks & condition variables");
    PR_DestroyLock(semaphore->cvar->lock);
    PR_DestroyCondVar(semaphore->cvar);
    PR_Free(semaphore);
}  /* PR_DestroySem */

PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
{
    PRSemaphore *semaphore;
    static PRBool unwarned = PR_TRUE;
    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (unwarned) unwarned = _PR_Obsolete(
        "PR_NewSem", "locks & condition variables");

    semaphore = PR_NEWZAP(PRSemaphore);
    if (NULL != semaphore)
    {
        PRLock *lock = PR_NewLock();
        if (NULL != lock)
        {
            semaphore->cvar = PR_NewCondVar(lock);
            if (NULL != semaphore->cvar)
            {
                semaphore->count = value;
                return semaphore;
            }
            PR_DestroyLock(lock);
        }
        PR_Free(semaphore);
    }
    return NULL;
}

/*
 * Define the interprocess named semaphore functions.
 * There are three implementations:
 * 1. POSIX semaphore based;
 * 2. System V semaphore based;
 * 3. unsupported (fails with PR_NOT_IMPLEMENTED_ERROR).
 */

#ifdef _PR_HAVE_POSIX_SEMAPHORES
#include <fcntl.h>

PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
    const char *name,
    PRIntn flags,
    PRIntn mode,
    PRUintn value)
{
    PRSem *sem;
    char osname[PR_IPC_NAME_SIZE];

    if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
        == PR_FAILURE)
    {
        return NULL;
    }

    sem = PR_NEW(PRSem);
    if (NULL == sem)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }

    if (flags & PR_SEM_CREATE)
    {
        int oflag = O_CREAT;

        if (flags & PR_SEM_EXCL) oflag |= O_EXCL;
        sem->sem = sem_open(osname, oflag, mode, value);
    }
    else
    {
#ifdef HPUX
        /* Pass 0 as the mode and value arguments to work around a bug. */
        sem->sem = sem_open(osname, 0, 0, 0);
#else
        sem->sem = sem_open(osname, 0);
#endif
    }
    if ((sem_t *) -1 == sem->sem)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        PR_Free(sem);
        return NULL;
    }
    return sem;
}

PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
{
    int rv;
    rv = sem_wait(sem->sem);
    if (0 != rv)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}

PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
{
    int rv;
    rv = sem_post(sem->sem);
    if (0 != rv)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}

PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
{
    int rv;
    rv = sem_close(sem->sem);
    if (0 != rv)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    PR_Free(sem);
    return PR_SUCCESS;
}

PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
{
    int rv;
    char osname[PR_IPC_NAME_SIZE];

    if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
        == PR_FAILURE)
    {
        return PR_FAILURE;
    }
    rv = sem_unlink(osname);
    if (0 != rv)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}
    
#elif defined(_PR_HAVE_SYSV_SEMAPHORES)

#include <fcntl.h>
#include <sys/sem.h>

/*
 * From the semctl(2) man page in glibc 2.0
 */
#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \
    || defined(FREEBSD) || defined(OPENBSD) || defined(BSDI) \
    || defined(DARWIN) || defined(SYMBIAN)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
    int val;
    struct semid_ds *buf;
    unsigned short  *array;
};
#endif

/*
 * 'a' (97) is the final closing price of NSCP stock.
 */
#define NSPR_IPC_KEY_ID 'a'  /* the id argument for ftok() */

#define NSPR_SEM_MODE 0666

PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
    const char *name,
    PRIntn flags,
    PRIntn mode,
    PRUintn value)
{
    PRSem *sem;
    key_t key;
    union semun arg;
    struct sembuf sop;
    struct semid_ds seminfo;
#define MAX_TRIES 60
    PRIntn i;
    char osname[PR_IPC_NAME_SIZE];

    if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
        == PR_FAILURE)
    {
        return NULL;
    }

    /* Make sure the file exists before calling ftok. */
    if (flags & PR_SEM_CREATE)
    {
        int osfd = open(osname, O_RDWR|O_CREAT, mode);
        if (-1 == osfd)
        {
            _PR_MD_MAP_OPEN_ERROR(errno);
            return NULL;
        }
        if (close(osfd) == -1)
        {
            _PR_MD_MAP_CLOSE_ERROR(errno);
            return NULL;
        }
    }
    key = ftok(osname, NSPR_IPC_KEY_ID);
    if ((key_t)-1 == key)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return NULL;
    }

    sem = PR_NEW(PRSem);
    if (NULL == sem)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }

    if (flags & PR_SEM_CREATE)
    {
        sem->semid = semget(key, 1, mode|IPC_CREAT|IPC_EXCL);
        if (sem->semid >= 0)
        {
            /* creator of a semaphore is responsible for initializing it */
            arg.val = 0;
            if (semctl(sem->semid, 0, SETVAL, arg) == -1)
            {
                _PR_MD_MAP_DEFAULT_ERROR(errno);
                PR_Free(sem);
                return NULL;
            }
            /* call semop to set sem_otime to nonzero */
            sop.sem_num = 0;
            sop.sem_op = value;
            sop.sem_flg = 0;
            if (semop(sem->semid, &sop, 1) == -1)
            {
                _PR_MD_MAP_DEFAULT_ERROR(errno);
                PR_Free(sem);
                return NULL;
            }
            return sem;
        }

        if (errno != EEXIST || flags & PR_SEM_EXCL)
        {
            _PR_MD_MAP_DEFAULT_ERROR(errno);
            PR_Free(sem);
            return NULL;
        }
    }

    sem->semid = semget(key, 1, NSPR_SEM_MODE);
    if (sem->semid == -1)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        PR_Free(sem);
        return NULL;
    }
    for (i = 0; i < MAX_TRIES; i++)
    {
        arg.buf = &seminfo;
        semctl(sem->semid, 0, IPC_STAT, arg);
        if (seminfo.sem_otime != 0) break;
        sleep(1);
    }
    if (i == MAX_TRIES)
    {
        PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
        PR_Free(sem);
        return NULL;
    }
    return sem;
}

PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
{
    struct sembuf sop;

    sop.sem_num = 0;
    sop.sem_op = -1;
    sop.sem_flg = 0;
    if (semop(sem->semid, &sop, 1) == -1)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}

PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
{
    struct sembuf sop;

    sop.sem_num = 0;
    sop.sem_op = 1;
    sop.sem_flg = 0;
    if (semop(sem->semid, &sop, 1) == -1)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}

PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
{
    PR_Free(sem);
    return PR_SUCCESS;
}

PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
{
    key_t key;
    int semid;
    /* On some systems (e.g., glibc 2.0) semctl requires a fourth argument */
    union semun unused;
    char osname[PR_IPC_NAME_SIZE];

    if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
        == PR_FAILURE)
    {
        return PR_FAILURE;
    }
    key = ftok(osname, NSPR_IPC_KEY_ID);
    if ((key_t) -1 == key)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    if (unlink(osname) == -1)
    {
        _PR_MD_MAP_UNLINK_ERROR(errno);
        return PR_FAILURE;
    }
    semid = semget(key, 1, NSPR_SEM_MODE);
    if (-1 == semid)
    {
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    unused.val = 0;
    if (semctl(semid, 0, IPC_RMID, unused) == -1)
    { 
        _PR_MD_MAP_DEFAULT_ERROR(errno);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}

#else /* neither POSIX nor System V semaphores are available */

PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
    const char *name,
    PRIntn flags,
    PRIntn mode,
    PRUintn value)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return NULL;
}

PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
}

PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
}

PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
}

PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
{
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
}

#endif /* end of interprocess named semaphore functions */

/**************************************************************/
/**************************************************************/
/******************ROUTINES FOR DCE EMULATION******************/
/**************************************************************/
/**************************************************************/

#include "prpdce.h"

PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
{
    PRIntn rv = pthread_mutex_trylock(&lock->mutex);
    if (rv == PT_TRYLOCK_SUCCESS)
    {
        PR_ASSERT(PR_FALSE == lock->locked);
        lock->locked = PR_TRUE;
        lock->owner = pthread_self();
    }
    /* XXX set error code? */
    return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;
}  /* PRP_TryLock */

PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
{
    PRCondVar *cv;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    cv = PR_NEW(PRCondVar);
    if (cv != NULL)
    {
        int rv;
        rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); 
        PR_ASSERT(0 == rv);
        cv->lock = _PR_NAKED_CV_LOCK;
    }
    return cv;
}  /* PRP_NewNakedCondVar */

PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar)
{
    int rv;
    rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
#if defined(DEBUG)
        memset(cvar, 0xaf, sizeof(PRCondVar));
#endif
    PR_Free(cvar);
}  /* PRP_DestroyNakedCondVar */

PR_IMPLEMENT(PRStatus) PRP_NakedWait(
    PRCondVar *cvar, PRLock *ml, PRIntervalTime timeout)
{
    PRIntn rv;
    PR_ASSERT(cvar != NULL);
    /* XXX do we really want to assert this in a naked wait? */
    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(ml->mutex));
    if (timeout == PR_INTERVAL_NO_TIMEOUT)
        rv = pthread_cond_wait(&cvar->cv, &ml->mutex);
    else
        rv = pt_TimedWait(&cvar->cv, &ml->mutex, timeout);
    if (rv != 0)
    {
        _PR_MD_MAP_DEFAULT_ERROR(rv);
        return PR_FAILURE;
    }
    return PR_SUCCESS;
}  /* PRP_NakedWait */

PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar)
{
    int rv;
    PR_ASSERT(cvar != NULL);
    rv = pthread_cond_signal(&cvar->cv);
    PR_ASSERT(0 == rv);
    return PR_SUCCESS;
}  /* PRP_NakedNotify */

PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar)
{
    int rv;
    PR_ASSERT(cvar != NULL);
    rv = pthread_cond_broadcast(&cvar->cv);
    PR_ASSERT(0 == rv);
    return PR_SUCCESS;
}  /* PRP_NakedBroadcast */

#endif  /* defined(_PR_PTHREADS) */

/* ptsynch.c */

deps/mozilla/nsprpub/pr/src/pthreads/ptthread.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
** File:            ptthread.c
** Descritpion:        Implemenation for threds using pthreds
** Exports:            ptthread.h
*/

#if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS)

#include "prlog.h"
#include "primpl.h"
#include "prpdce.h"

#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

#ifdef SYMBIAN
/* In Open C sched_get_priority_min/max do not work properly, so we undefine
 * _POSIX_THREAD_PRIORITY_SCHEDULING here.
 */
#undef _POSIX_THREAD_PRIORITY_SCHEDULING
#endif

/*
 * Record whether or not we have the privilege to set the scheduling
 * policy and priority of threads.  0 means that privilege is available.
 * EPERM means that privilege is not available.
 */

static PRIntn pt_schedpriv = 0;
extern PRLock *_pr_sleeplock;

static struct _PT_Bookeeping
{
    PRLock *ml;                 /* a lock to protect ourselves */
    PRCondVar *cv;              /* used to signal global things */
    PRInt32 system, user;       /* a count of the two different types */
    PRUintn this_many;          /* number of threads allowed for exit */
    pthread_key_t key;          /* private private data key */
    PRThread *first, *last;     /* list of threads we know about */
#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    PRInt32 minPrio, maxPrio;   /* range of scheduling priorities */
#endif
} pt_book = {0};

static void _pt_thread_death(void *arg);
static void _pt_thread_death_internal(void *arg, PRBool callDestructors);
static void init_pthread_gc_support(void);

#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
static PRIntn pt_PriorityMap(PRThreadPriority pri)
{
#ifdef NTO
    /* This priority algorithm causes lots of problems on Neutrino
     * for now I have just hard coded everything to run at priority 10
     * until I can come up with a new algorithm.
     *     Jerry.Kirk@Nexwarecorp.com
     */
    return 10;
#else
    return pt_book.minPrio +
	    pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST;
#endif
}
#endif

/*
** Initialize a stack for a native pthread thread
*/
static void _PR_InitializeStack(PRThreadStack *ts)
{
    if( ts && (ts->stackTop == 0) ) {
        ts->allocBase = (char *) &ts;
        ts->allocSize = ts->stackSize;

        /*
        ** Setup stackTop and stackBottom values.
        */
#ifdef HAVE_STACK_GROWING_UP
        ts->stackBottom = ts->allocBase + ts->stackSize;
        ts->stackTop = ts->allocBase;
#else
        ts->stackTop    = ts->allocBase;
        ts->stackBottom = ts->allocBase - ts->stackSize;
#endif
    }
}

static void *_pt_root(void *arg)
{
    PRIntn rv;
    PRThread *thred = (PRThread*)arg;
    PRBool detached = (thred->state & PT_THREAD_DETACHED) ? PR_TRUE : PR_FALSE;

    /*
     * Both the parent thread and this new thread set thred->id.
     * The new thread must ensure that thred->id is set before
     * it executes its startFunc.  The parent thread must ensure
     * that thred->id is set before PR_CreateThread() returns.
     * Both threads set thred->id without holding a lock.  Since
     * they are writing the same value, this unprotected double
     * write should be safe.
     */
    thred->id = pthread_self();

    /*
    ** DCE Threads can't detach during creation, so do it late.
    ** I would like to do it only here, but that doesn't seem
    ** to work.
    */
#if defined(_PR_DCETHREADS)
    if (detached)
    {
        /* pthread_detach() modifies its argument, so we must pass a copy */
        pthread_t self = thred->id;
        rv = pthread_detach(&self);
        PR_ASSERT(0 == rv);
    }
#endif /* defined(_PR_DCETHREADS) */

    /* Set up the thread stack information */
    _PR_InitializeStack(thred->stack);

    /*
     * Set within the current thread the pointer to our object.
     * This object will be deleted when the thread termintates,
     * whether in a join or detached (see _PR_InitThreads()).
     */
    rv = pthread_setspecific(pt_book.key, thred);
    PR_ASSERT(0 == rv);

    /* make the thread visible to the rest of the runtime */
    PR_Lock(pt_book.ml);

    /* If this is a GCABLE thread, set its state appropriately */
    if (thred->suspend & PT_THREAD_SETGCABLE)
	    thred->state |= PT_THREAD_GCABLE;
    thred->suspend = 0;

    thred->prev = pt_book.last;
    if (pt_book.last)
        pt_book.last->next = thred;
    else
        pt_book.first = thred;
    thred->next = NULL;
    pt_book.last = thred;
    PR_Unlock(pt_book.ml);

    thred->startFunc(thred->arg);  /* make visible to the client */

    /* unhook the thread from the runtime */
    PR_Lock(pt_book.ml);
    /*
     * At this moment, PR_CreateThread() may not have set thred->id yet.
     * It is safe for a detached thread to free thred only after
     * PR_CreateThread() has set thred->id.
     */
    if (detached)
    {
        while (!thred->okToDelete)
            PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
    }

    if (thred->state & PT_THREAD_SYSTEM)
        pt_book.system -= 1;
    else if (--pt_book.user == pt_book.this_many)
        PR_NotifyAllCondVar(pt_book.cv);
    if (NULL == thred->prev)
        pt_book.first = thred->next;
    else
        thred->prev->next = thred->next;
    if (NULL == thred->next)
        pt_book.last = thred->prev;
    else
        thred->next->prev = thred->prev;
    PR_Unlock(pt_book.ml);

    /*
    * Here we set the pthread's backpointer to the PRThread to NULL.
    * Otherwise the destructor would get called eagerly as the thread
    * returns to the pthread runtime. The joining thread would them be
    * the proud possessor of a dangling reference. However, this is the
    * last chance to delete the object if the thread is detached, so
    * just let the destructor do the work.
    */
    if (PR_FALSE == detached)
    {
        /* Call TPD destructors on this thread. */
        _PR_DestroyThreadPrivate(thred);
        rv = pthread_setspecific(pt_book.key, NULL);
        PR_ASSERT(0 == rv);
    }

    return NULL;
}  /* _pt_root */

static PRThread* pt_AttachThread(void)
{
    PRThread *thred = NULL;

    /*
     * NSPR must have been initialized when PR_AttachThread is called.
     * We cannot have PR_AttachThread call implicit initialization
     * because if multiple threads call PR_AttachThread simultaneously,
     * NSPR may be initialized more than once.
     * We can't call any function that calls PR_GetCurrentThread()
     * either (e.g., PR_SetError()) as that will result in infinite
     * recursion.
     */
    if (!_pr_initialized) return NULL;

    /* PR_NEWZAP must not call PR_GetCurrentThread() */
    thred = PR_NEWZAP(PRThread);
    if (NULL != thred)
    {
        int rv;

        thred->priority = PR_PRIORITY_NORMAL;
        thred->id = pthread_self();
        rv = pthread_setspecific(pt_book.key, thred);
        PR_ASSERT(0 == rv);

        thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN;
        PR_Lock(pt_book.ml);

        /* then put it into the list */
        thred->prev = pt_book.last;
        if (pt_book.last)
            pt_book.last->next = thred;
        else
            pt_book.first = thred;
        thred->next = NULL;
        pt_book.last = thred;
        PR_Unlock(pt_book.ml);

    }
    return thred;  /* may be NULL */
}  /* pt_AttachThread */

static PRThread* _PR_CreateThread(
    PRThreadType type, void (*start)(void *arg),
    void *arg, PRThreadPriority priority, PRThreadScope scope,
    PRThreadState state, PRUint32 stackSize, PRBool isGCAble)
{
    int rv;
    PRThread *thred;
    pthread_attr_t tattr;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)priority)
        priority = PR_PRIORITY_FIRST;
    else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)priority)
        priority = PR_PRIORITY_LAST;

    rv = _PT_PTHREAD_ATTR_INIT(&tattr);
    PR_ASSERT(0 == rv);

    if (EPERM != pt_schedpriv)
    {
#if !defined(_PR_DCETHREADS) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
        struct sched_param schedule;
#endif

#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
        rv = pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
        PR_ASSERT(0 == rv);
#endif

        /* Use the default scheduling policy */

#if defined(_PR_DCETHREADS)
        rv = pthread_attr_setprio(&tattr, pt_PriorityMap(priority));
        PR_ASSERT(0 == rv);
#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
        rv = pthread_attr_getschedparam(&tattr, &schedule);
        PR_ASSERT(0 == rv);
        schedule.sched_priority = pt_PriorityMap(priority);
        rv = pthread_attr_setschedparam(&tattr, &schedule);
        PR_ASSERT(0 == rv);
#ifdef NTO
        rv = pthread_attr_setschedpolicy(&tattr, SCHED_RR); /* Round Robin */
        PR_ASSERT(0 == rv);
#endif
#endif /* !defined(_PR_DCETHREADS) */
    }

    /*
     * DCE threads can't set detach state before creating the thread.
     * AIX can't set detach late. Why can't we all just get along?
     */
#if !defined(_PR_DCETHREADS)
    rv = pthread_attr_setdetachstate(&tattr,
        ((PR_JOINABLE_THREAD == state) ?
            PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED));
    PR_ASSERT(0 == rv);
#endif /* !defined(_PR_DCETHREADS) */

    /*
     * If stackSize is 0, we use the default pthread stack size.
     */
    if (stackSize)
    {
#ifdef _MD_MINIMUM_STACK_SIZE
        if (stackSize < _MD_MINIMUM_STACK_SIZE)
            stackSize = _MD_MINIMUM_STACK_SIZE;
#endif
        rv = pthread_attr_setstacksize(&tattr, stackSize);
        PR_ASSERT(0 == rv);
    }

    thred = PR_NEWZAP(PRThread);
    if (NULL == thred)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, errno);
        goto done;
    }
    else
    {
        pthread_t id;

        thred->arg = arg;
        thred->startFunc = start;
        thred->priority = priority;
        if (PR_UNJOINABLE_THREAD == state)
            thred->state |= PT_THREAD_DETACHED;

        if (PR_LOCAL_THREAD == scope)
        	scope = PR_GLOBAL_THREAD;
			
        if (PR_GLOBAL_BOUND_THREAD == scope) {
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    		rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
			if (rv) {
				/*
				 * system scope not supported
				 */
        		scope = PR_GLOBAL_THREAD;
				/*
				 * reset scope
				 */
    			rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
    			PR_ASSERT(0 == rv);
			}
#endif
		}
        if (PR_GLOBAL_THREAD == scope)
            thred->state |= PT_THREAD_GLOBAL;
        else if (PR_GLOBAL_BOUND_THREAD == scope)
            thred->state |= (PT_THREAD_GLOBAL | PT_THREAD_BOUND);
		else	/* force it global */
            thred->state |= PT_THREAD_GLOBAL;
        if (PR_SYSTEM_THREAD == type)
            thred->state |= PT_THREAD_SYSTEM;

        thred->suspend =(isGCAble) ? PT_THREAD_SETGCABLE : 0;

        thred->stack = PR_NEWZAP(PRThreadStack);
        if (thred->stack == NULL) {
            PRIntn oserr = errno;
            PR_Free(thred);  /* all that work ... poof! */
            PR_SetError(PR_OUT_OF_MEMORY_ERROR, oserr);
            thred = NULL;  /* and for what? */
            goto done;
        }
        thred->stack->stackSize = stackSize;
        thred->stack->thr = thred;

#ifdef PT_NO_SIGTIMEDWAIT
        pthread_mutex_init(&thred->suspendResumeMutex,NULL);
        pthread_cond_init(&thred->suspendResumeCV,NULL);
#endif

        /* make the thread counted to the rest of the runtime */
        PR_Lock(pt_book.ml);
        if (PR_SYSTEM_THREAD == type)
            pt_book.system += 1;
        else pt_book.user += 1;
        PR_Unlock(pt_book.ml);

        /*
         * We pass a pointer to a local copy (instead of thred->id)
         * to pthread_create() because who knows what wacky things
         * pthread_create() may be doing to its argument.
         */
        rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);

#if !defined(_PR_DCETHREADS)
        if (EPERM == rv)
        {
#if defined(IRIX)
        	if (PR_GLOBAL_BOUND_THREAD == scope) {
				/*
				 * SCOPE_SYSTEM requires appropriate privilege
				 * reset to process scope and try again
				 */
    			rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
    			PR_ASSERT(0 == rv);
            	thred->state &= ~PT_THREAD_BOUND;
			}
#else
            /* Remember that we don't have thread scheduling privilege. */
            pt_schedpriv = EPERM;
            PR_LOG(_pr_thread_lm, PR_LOG_MIN,
                ("_PR_CreateThread: no thread scheduling privilege"));
            /* Try creating the thread again without setting priority. */
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
            rv = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED);
            PR_ASSERT(0 == rv);
#endif
#endif	/* IRIX */
            rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);
        }
#endif

        if (0 != rv)
        {
#if defined(_PR_DCETHREADS)
            PRIntn oserr = errno;
#else
            PRIntn oserr = rv;
#endif
            PR_Lock(pt_book.ml);
            if (thred->state & PT_THREAD_SYSTEM)
                pt_book.system -= 1;
            else if (--pt_book.user == pt_book.this_many)
                PR_NotifyAllCondVar(pt_book.cv);
            PR_Unlock(pt_book.ml);

            PR_Free(thred->stack);
            PR_Free(thred);  /* all that work ... poof! */
            PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, oserr);
            thred = NULL;  /* and for what? */
            goto done;
        }

        /*
         * Both the parent thread and this new thread set thred->id.
         * The parent thread must ensure that thred->id is set before
         * PR_CreateThread() returns.  (See comments in _pt_root().)
         */
        thred->id = id;

        /*
         * If the new thread is detached, tell it that PR_CreateThread()
         * has set thred->id so it's ok to delete thred.
         */
        if (PR_UNJOINABLE_THREAD == state)
        {
            PR_Lock(pt_book.ml);
            thred->okToDelete = PR_TRUE;
            PR_NotifyAllCondVar(pt_book.cv);
            PR_Unlock(pt_book.ml);
        }
    }

done:
    rv = _PT_PTHREAD_ATTR_DESTROY(&tattr);
    PR_ASSERT(0 == rv);

    return thred;
}  /* _PR_CreateThread */

PR_IMPLEMENT(PRThread*) PR_CreateThread(
    PRThreadType type, void (*start)(void *arg), void *arg,
    PRThreadPriority priority, PRThreadScope scope,
    PRThreadState state, PRUint32 stackSize)
{
    return _PR_CreateThread(
        type, start, arg, priority, scope, state, stackSize, PR_FALSE);
} /* PR_CreateThread */

PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(
    PRThreadType type, void (*start)(void *arg), void *arg, 
    PRThreadPriority priority, PRThreadScope scope,
    PRThreadState state, PRUint32 stackSize)
{
    return _PR_CreateThread(
        type, start, arg, priority, scope, state, stackSize, PR_TRUE);
}  /* PR_CreateThreadGCAble */

PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thred)
{
    return thred->environment;
}  /* GetExecutionEnvironment */
 
PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thred, void *env)
{
    thred->environment = env;
}  /* SetExecutionEnvironment */

PR_IMPLEMENT(PRThread*) PR_AttachThread(
    PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
{
    return PR_GetCurrentThread();
}  /* PR_AttachThread */


PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
{
    int rv = -1;
    void *result = NULL;
    PR_ASSERT(thred != NULL);

    if ((0xafafafaf == thred->state)
    || (PT_THREAD_DETACHED == (PT_THREAD_DETACHED & thred->state))
    || (PT_THREAD_FOREIGN == (PT_THREAD_FOREIGN & thred->state)))
    {
        /*
         * This might be a bad address, but if it isn't, the state should
         * either be an unjoinable thread or it's already had the object
         * deleted. However, the client that called join on a detached
         * thread deserves all the rath I can muster....
         */
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        PR_LogPrint(
            "PR_JoinThread: %p not joinable | already smashed\n", thred);
    }
    else
    {
        pthread_t id = thred->id;
        rv = pthread_join(id, &result);
        PR_ASSERT(rv == 0 && result == NULL);
        if (0 == rv)
        {
#ifdef _PR_DCETHREADS
            rv = pthread_detach(&id);
            PR_ASSERT(0 == rv);
#endif
            /*
             * PR_FALSE, because the thread already called the TPD
             * destructors before exiting _pt_root.
             */
            _pt_thread_death_internal(thred, PR_FALSE);
        }
        else
        {
            PRErrorCode prerror;
            switch (rv)
            {
                case EINVAL:  /* not a joinable thread */
                case ESRCH:   /* no thread with given ID */
                    prerror = PR_INVALID_ARGUMENT_ERROR;
                    break;
                case EDEADLK: /* a thread joining with itself */
                    prerror = PR_DEADLOCK_ERROR;
                    break;
                default:
                    prerror = PR_UNKNOWN_ERROR;
                    break;
            }
            PR_SetError(prerror, rv);
        }
    }
    return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
}  /* PR_JoinThread */

PR_IMPLEMENT(void) PR_DetachThread(void)
{
    void *thred;
    int rv;

    _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
    if (NULL == thred) return;
    _pt_thread_death(thred);
    rv = pthread_setspecific(pt_book.key, NULL);
    PR_ASSERT(0 == rv);
}  /* PR_DetachThread */

PR_IMPLEMENT(PRThread*) PR_GetCurrentThread(void)
{
    void *thred;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
    if (NULL == thred) thred = pt_AttachThread();
    PR_ASSERT(NULL != thred);
    return (PRThread*)thred;
}  /* PR_GetCurrentThread */

PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thred)
{
    return (thred->state & PT_THREAD_BOUND) ?
        PR_GLOBAL_BOUND_THREAD : PR_GLOBAL_THREAD;
}  /* PR_GetThreadScope() */

PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thred)
{
    return (thred->state & PT_THREAD_SYSTEM) ?
        PR_SYSTEM_THREAD : PR_USER_THREAD;
}

PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thred)
{
    return (thred->state & PT_THREAD_DETACHED) ?
        PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD;
}  /* PR_GetThreadState */

PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thred)
{
    PR_ASSERT(thred != NULL);
    return thred->priority;
}  /* PR_GetThreadPriority */

PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri)
{
    PRIntn rv = -1;

    PR_ASSERT(NULL != thred);

    if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)newPri)
        newPri = PR_PRIORITY_FIRST;
    else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)newPri)
        newPri = PR_PRIORITY_LAST;

#if defined(_PR_DCETHREADS)
    rv = pthread_setprio(thred->id, pt_PriorityMap(newPri));
    /* pthread_setprio returns the old priority */
#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    if (EPERM != pt_schedpriv)
    {
        int policy;
        struct sched_param schedule;

        rv = pthread_getschedparam(thred->id, &policy, &schedule);
        if(0 == rv) {
			schedule.sched_priority = pt_PriorityMap(newPri);
			rv = pthread_setschedparam(thred->id, policy, &schedule);
			if (EPERM == rv)
			{
				pt_schedpriv = EPERM;
				PR_LOG(_pr_thread_lm, PR_LOG_MIN,
					("PR_SetThreadPriority: no thread scheduling privilege"));
			}
		}
		if (rv != 0)
			rv = -1;
    }
#endif

    thred->priority = newPri;
}  /* PR_SetThreadPriority */

PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred)
{
    /*
    ** If the target thread indicates that it's waiting,
    ** find the condition and broadcast to it. Broadcast
    ** since we don't know which thread (if there are more
    ** than one). This sounds risky, but clients must
    ** test their invariants when resumed from a wait and
    ** I don't expect very many threads to be waiting on
    ** a single condition and I don't expect interrupt to
    ** be used very often.
    **
    ** I don't know why I thought this would work. Must have
    ** been one of those weaker momements after I'd been
    ** smelling the vapors.
    **
    ** Even with the followng changes it is possible that
    ** the pointer to the condition variable is pointing
    ** at a bogus value. Will the unerlying code detect
    ** that?
    */
    PRCondVar *cv;
    PR_ASSERT(NULL != thred);
    if (NULL == thred) return PR_FAILURE;

    thred->state |= PT_THREAD_ABORTED;

    cv = thred->waiting;
    if ((NULL != cv) && !thred->interrupt_blocked)
    {
        PRIntn rv;
        (void)PR_ATOMIC_INCREMENT(&cv->notify_pending);
        rv = pthread_cond_broadcast(&cv->cv);
        PR_ASSERT(0 == rv);
        if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
            PR_DestroyCondVar(cv);
    }
    return PR_SUCCESS;
}  /* PR_Interrupt */

PR_IMPLEMENT(void) PR_ClearInterrupt(void)
{
    PRThread *me = PR_GetCurrentThread();
    me->state &= ~PT_THREAD_ABORTED;
}  /* PR_ClearInterrupt */

PR_IMPLEMENT(void) PR_BlockInterrupt(void)
{
    PRThread *me = PR_GetCurrentThread();
    _PT_THREAD_BLOCK_INTERRUPT(me);
}  /* PR_BlockInterrupt */

PR_IMPLEMENT(void) PR_UnblockInterrupt(void)
{
    PRThread *me = PR_GetCurrentThread();
    _PT_THREAD_UNBLOCK_INTERRUPT(me);
}  /* PR_UnblockInterrupt */

PR_IMPLEMENT(PRStatus) PR_Yield(void)
{
    static PRBool warning = PR_TRUE;
    if (warning) warning = _PR_Obsolete(
        "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)");
    return PR_Sleep(PR_INTERVAL_NO_WAIT);
}

PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks)
{
    PRStatus rv = PR_SUCCESS;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (PR_INTERVAL_NO_WAIT == ticks)
    {
        _PT_PTHREAD_YIELD();
    }
    else
    {
        PRCondVar *cv;
        PRIntervalTime timein;

        timein = PR_IntervalNow();
        cv = PR_NewCondVar(_pr_sleeplock);
        PR_ASSERT(cv != NULL);
        PR_Lock(_pr_sleeplock);
        do
        {
            PRIntervalTime now = PR_IntervalNow();
            PRIntervalTime delta = now - timein;
            if (delta > ticks) break;
            rv = PR_WaitCondVar(cv, ticks - delta);
        } while (PR_SUCCESS == rv);
        PR_Unlock(_pr_sleeplock);
        PR_DestroyCondVar(cv);
    }
    return rv;
}  /* PR_Sleep */

static void _pt_thread_death(void *arg)
{
    void *thred;
    int rv;

    _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
    if (NULL == thred)
    {
        /*
         * Have PR_GetCurrentThread return the expected value to the
         * destructors.
         */
        rv = pthread_setspecific(pt_book.key, arg);
        PR_ASSERT(0 == rv);
    }

    /* PR_TRUE for: call destructors */ 
    _pt_thread_death_internal(arg, PR_TRUE);

    if (NULL == thred)
    {
        rv = pthread_setspecific(pt_book.key, NULL);
        PR_ASSERT(0 == rv);
    }
}

static void _pt_thread_death_internal(void *arg, PRBool callDestructors)
{
    PRThread *thred = (PRThread*)arg;

    if (thred->state & (PT_THREAD_FOREIGN|PT_THREAD_PRIMORD))
    {
        PR_Lock(pt_book.ml);
        if (NULL == thred->prev)
            pt_book.first = thred->next;
        else
            thred->prev->next = thred->next;
        if (NULL == thred->next)
            pt_book.last = thred->prev;
        else
            thred->next->prev = thred->prev;
        PR_Unlock(pt_book.ml);
    }
    if (callDestructors)
        _PR_DestroyThreadPrivate(thred);
    PR_Free(thred->privateData);
    if (NULL != thred->errorString)
        PR_Free(thred->errorString);
    PR_Free(thred->stack);
    if (NULL != thred->syspoll_list)
        PR_Free(thred->syspoll_list);
#if defined(_PR_POLL_WITH_SELECT)
    if (NULL != thred->selectfd_list)
        PR_Free(thred->selectfd_list);
#endif
#if defined(DEBUG)
    memset(thred, 0xaf, sizeof(PRThread));
#endif /* defined(DEBUG) */
    PR_Free(thred);
}  /* _pt_thread_death */

void _PR_InitThreads(
    PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
{
    int rv;
    PRThread *thred;

#ifdef _PR_NEED_PTHREAD_INIT
    /*
     * On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily
     * initialized, but pthread_self() fails to initialize
     * pthreads and hence returns a null thread ID if invoked
     * by the primordial thread before any other pthread call.
     * So we explicitly initialize pthreads here.
     */
    pthread_init();
#endif

#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
#if defined(FREEBSD)
    {
    pthread_attr_t attr;
    int policy;
    /* get the min and max priorities of the default policy */
    pthread_attr_init(&attr);
    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    pthread_attr_getschedpolicy(&attr, &policy);
    pt_book.minPrio = sched_get_priority_min(policy);
    PR_ASSERT(-1 != pt_book.minPrio);
    pt_book.maxPrio = sched_get_priority_max(policy);
    PR_ASSERT(-1 != pt_book.maxPrio);
    pthread_attr_destroy(&attr);
    }
#else
    /*
    ** These might be function evaluations
    */
    pt_book.minPrio = PT_PRIO_MIN;
    pt_book.maxPrio = PT_PRIO_MAX;
#endif
#endif
    
    PR_ASSERT(NULL == pt_book.ml);
    pt_book.ml = PR_NewLock();
    PR_ASSERT(NULL != pt_book.ml);
    pt_book.cv = PR_NewCondVar(pt_book.ml);
    PR_ASSERT(NULL != pt_book.cv);
    thred = PR_NEWZAP(PRThread);
    PR_ASSERT(NULL != thred);
    thred->arg = NULL;
    thred->startFunc = NULL;
    thred->priority = priority;
    thred->id = pthread_self();

    thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD);
    if (PR_SYSTEM_THREAD == type)
    {
        thred->state |= PT_THREAD_SYSTEM;
        pt_book.system += 1;
	    pt_book.this_many = 0;
    }
    else
    {
	    pt_book.user += 1;
	    pt_book.this_many = 1;
    }
    thred->next = thred->prev = NULL;
    pt_book.first = pt_book.last = thred;

    thred->stack = PR_NEWZAP(PRThreadStack);
    PR_ASSERT(thred->stack != NULL);
    thred->stack->stackSize = 0;
    thred->stack->thr = thred;
	_PR_InitializeStack(thred->stack);

    /*
     * Create a key for our use to store a backpointer in the pthread
     * to our PRThread object. This object gets deleted when the thread
     * returns from its root in the case of a detached thread. Other
     * threads delete the objects in Join.
     *
     * NB: The destructor logic seems to have a bug so it isn't used.
     * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998.
     * More info - the problem is that pthreads calls the destructor
     * eagerly as the thread returns from its root, rather than lazily
     * after the thread is joined. Therefore, threads that are joining
     * and holding PRThread references are actually holding pointers to
     * nothing.
     */
    rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death);
    PR_ASSERT(0 == rv);
    rv = pthread_setspecific(pt_book.key, thred);
    PR_ASSERT(0 == rv);    
    PR_SetThreadPriority(thred, priority);
}  /* _PR_InitThreads */

#ifdef __GNUC__
/*
 * GCC supports the constructor and destructor attributes as of
 * version 2.5.
 */
static void _PR_Fini(void) __attribute__ ((destructor));
#elif defined(__SUNPRO_C)
/*
 * Sun Studio compiler
 */
#pragma fini(_PR_Fini)
static void _PR_Fini(void);
#elif defined(HPUX)
/*
 * Current versions of HP C compiler define __HP_cc.
 * HP C compiler A.11.01.20 doesn't define __HP_cc.
 */
#if defined(__ia64) || defined(_LP64)
#pragma FINI "_PR_Fini"
static void _PR_Fini(void);
#else
/*
 * Only HP-UX 10.x style initializers are supported in 32-bit links.
 * Need to use the +I PR_HPUX10xInit linker option.
 */
#include <dl.h>

static void _PR_Fini(void);

void PR_HPUX10xInit(shl_t handle, int loading)
{
    /*
     * This function is called when a shared library is loaded as well
     * as when the shared library is unloaded.  Note that it may not
     * be called when the user's program terminates.
     *
     * handle is the shl_load API handle for the shared library being
     * initialized.
     *
     * loading is non-zero at startup and zero at termination.
     */
    if (loading) {
	/* ... do some initializations ... */
    } else {
	_PR_Fini();
    }
}
#endif
#elif defined(AIX)
/* Need to use the -binitfini::_PR_Fini linker option. */
#endif

void _PR_Fini(void)
{
    void *thred;
    int rv;

    if (!_pr_initialized) return;

    _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
    if (NULL != thred)
    {
        /*
         * PR_FALSE, because it is unsafe to call back to the 
         * thread private data destructors at final cleanup.
         */
        _pt_thread_death_internal(thred, PR_FALSE);
        rv = pthread_setspecific(pt_book.key, NULL);
        PR_ASSERT(0 == rv);
    }
    /* TODO: free other resources used by NSPR */
    /* _pr_initialized = PR_FALSE; */
}  /* _PR_Fini */

PR_IMPLEMENT(PRStatus) PR_Cleanup(void)
{
    PRThread *me = PR_GetCurrentThread();
    int rv;
    PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
    PR_ASSERT(me->state & PT_THREAD_PRIMORD);
    if (me->state & PT_THREAD_PRIMORD)
    {
        PR_Lock(pt_book.ml);
        while (pt_book.user > pt_book.this_many)
            PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
        if (me->state & PT_THREAD_SYSTEM)
            pt_book.system -= 1;
        else
            pt_book.user -= 1;
        PR_Unlock(pt_book.ml);

        _PR_MD_EARLY_CLEANUP();

        _PR_CleanupMW();
        _PR_CleanupTime();
        _PR_CleanupDtoa();
        _PR_CleanupCallOnce();
        _PR_ShutdownLinker();
        _PR_LogCleanup();
        _PR_CleanupNet();
        /* Close all the fd's before calling _PR_CleanupIO */
        _PR_CleanupIO();
        _PR_CleanupCMon();

        _pt_thread_death(me);
        rv = pthread_setspecific(pt_book.key, NULL);
        PR_ASSERT(0 == rv);
        /*
         * I am not sure if it's safe to delete the cv and lock here,
         * since there may still be "system" threads around. If this
         * call isn't immediately prior to exiting, then there's a
         * problem.
         */
        if (0 == pt_book.system)
        {
            PR_DestroyCondVar(pt_book.cv); pt_book.cv = NULL;
            PR_DestroyLock(pt_book.ml); pt_book.ml = NULL;
        }
        PR_DestroyLock(_pr_sleeplock);
        _pr_sleeplock = NULL;
        _PR_CleanupLayerCache();
        _PR_CleanupEnv();
#ifdef _PR_ZONE_ALLOCATOR
        _PR_DestroyZones();
#endif
        _pr_initialized = PR_FALSE;
        return PR_SUCCESS;
    }
    return PR_FAILURE;
}  /* PR_Cleanup */

PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
{
    _exit(status);
}

PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred)
{
#if defined(_PR_DCETHREADS)
    return (PRUint32)&thred->id;  /* this is really a sham! */
#else
    return (PRUint32)thred->id;  /* and I don't know what they will do with it */
#endif
}

/*
 * $$$
 * The following two thread-to-processor affinity functions are not
 * yet implemented for pthreads.  By the way, these functions should return
 * PRStatus rather than PRInt32 to indicate the success/failure status.
 * $$$
 */

PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask)
{
    return 0;  /* not implemented */
}

PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask )
{
    return 0;  /* not implemented */
}

PR_IMPLEMENT(void)
PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg)
{
    thread->dump = dump;
    thread->dumpArg = arg;
}

/* 
 * Garbage collection support follows.
 */

#if defined(_PR_DCETHREADS)

/*
 * statics for Garbage Collection support.  We don't need to protect these
 * signal masks since the garbage collector itself is protected by a lock
 * and multiple threads will not be garbage collecting at the same time.
 */
static sigset_t javagc_vtalarm_sigmask;
static sigset_t javagc_intsoff_sigmask;

#else /* defined(_PR_DCETHREADS) */

/* a bogus signal mask for forcing a timed wait */
/* Not so bogus in AIX as we really do a sigwait */
static sigset_t sigwait_set;

static struct timespec onemillisec = {0, 1000000L};
#ifndef PT_NO_SIGTIMEDWAIT
static struct timespec hundredmillisec = {0, 100000000L};
#endif

static void suspend_signal_handler(PRIntn sig);

#ifdef PT_NO_SIGTIMEDWAIT
static void null_signal_handler(PRIntn sig);
#endif

#endif /* defined(_PR_DCETHREADS) */

/*
 * Linux pthreads use SIGUSR1 and SIGUSR2 internally, which
 * conflict with the use of these two signals in our GC support.
 * So we don't know how to support GC on Linux pthreads.
 */
static void init_pthread_gc_support(void)
{
#ifndef SYMBIAN
    PRIntn rv;

#if defined(_PR_DCETHREADS)
	rv = sigemptyset(&javagc_vtalarm_sigmask);
    PR_ASSERT(0 == rv);
	rv = sigaddset(&javagc_vtalarm_sigmask, SIGVTALRM);
    PR_ASSERT(0 == rv);
#else  /* defined(_PR_DCETHREADS) */
	{
	    struct sigaction sigact_usr2;

	    sigact_usr2.sa_handler = suspend_signal_handler;
	    sigact_usr2.sa_flags = SA_RESTART;
	    sigemptyset (&sigact_usr2.sa_mask);

        rv = sigaction (SIGUSR2, &sigact_usr2, NULL);
        PR_ASSERT(0 == rv);

        sigemptyset (&sigwait_set);
#if defined(PT_NO_SIGTIMEDWAIT)
        sigaddset (&sigwait_set, SIGUSR1);
#else
        sigaddset (&sigwait_set, SIGUSR2);
#endif  /* defined(PT_NO_SIGTIMEDWAIT) */
	}
#if defined(PT_NO_SIGTIMEDWAIT)
	{
	    struct sigaction sigact_null;
	    sigact_null.sa_handler = null_signal_handler;
	    sigact_null.sa_flags = SA_RESTART;
	    sigemptyset (&sigact_null.sa_mask);
        rv = sigaction (SIGUSR1, &sigact_null, NULL);
	    PR_ASSERT(0 ==rv); 
    }
#endif  /* defined(PT_NO_SIGTIMEDWAIT) */
#endif /* defined(_PR_DCETHREADS) */
#endif /* SYMBIAN */
}

PR_IMPLEMENT(void) PR_SetThreadGCAble(void)
{
    PR_Lock(pt_book.ml);
	PR_GetCurrentThread()->state |= PT_THREAD_GCABLE;
    PR_Unlock(pt_book.ml);
}

PR_IMPLEMENT(void) PR_ClearThreadGCAble(void)
{
    PR_Lock(pt_book.ml);
	PR_GetCurrentThread()->state &= (~PT_THREAD_GCABLE);
    PR_Unlock(pt_book.ml);
}

#if defined(DEBUG)
static PRBool suspendAllOn = PR_FALSE;
#endif

static PRBool suspendAllSuspended = PR_FALSE;

PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
{
    PRIntn count = 0;
    PRStatus rv = PR_SUCCESS;
    PRThread* thred = pt_book.first;

#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
#if !defined(_PR_DCETHREADS)
    PRThread *me = PR_GetCurrentThread();
#endif
#endif

    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_EnumerateThreads\n"));
    /*
     * $$$
     * Need to suspend all threads other than me before doing this.
     * This is really a gross and disgusting thing to do. The only
     * good thing is that since all other threads are suspended, holding
     * the lock during a callback seems like child's play.
     * $$$
     */
    PR_ASSERT(suspendAllOn);

    while (thred != NULL)
    {
        /* Steve Morse, 4-23-97: Note that we can't walk a queue by taking
         * qp->next after applying the function "func".  In particular, "func"
         * might remove the thread from the queue and put it into another one in
         * which case qp->next no longer points to the next entry in the original
         * queue.
         *
         * To get around this problem, we save qp->next in qp_next before applying
         * "func" and use that saved value as the next value after applying "func".
         */
        PRThread* next = thred->next;

        if (_PT_IS_GCABLE_THREAD(thred))
        {
#if !defined(_PR_DCETHREADS)
            PR_ASSERT((thred == me) || (thred->suspend & PT_THREAD_SUSPENDED));
#endif
            PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
                   ("In PR_EnumerateThreads callback thread %p thid = %X\n", 
                    thred, thred->id));

            rv = func(thred, count++, arg);
            if (rv != PR_SUCCESS)
                return rv;
        }
        thred = next;
    }
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
	   ("End PR_EnumerateThreads count = %d \n", count));
    return rv;
}  /* PR_EnumerateThreads */

/*
 * PR_SuspendAll and PR_ResumeAll are called during garbage collection.  The strategy 
 * we use is to send a SIGUSR2 signal to every gc able thread that we intend to suspend.
 * The signal handler will record the stack pointer and will block until resumed by
 * the resume call.  Since the signal handler is the last routine called for the
 * suspended thread, the stack pointer will also serve as a place where all the
 * registers have been saved on the stack for the previously executing routines.
 *
 * Through global variables, we also make sure that PR_Suspend and PR_Resume does not
 * proceed until the thread is suspended or resumed.
 */

#if !defined(_PR_DCETHREADS)

/*
 * In the signal handler, we can not use condition variable notify or wait.
 * This does not work consistently across all pthread platforms.  We also can not 
 * use locking since that does not seem to work reliably across platforms.
 * Only thing we can do is yielding while testing for a global condition
 * to change.  This does work on pthread supported platforms.  We may have
 * to play with priortities if there are any problems detected.
 */

 /* 
  * In AIX, you cannot use ANY pthread calls in the signal handler except perhaps
  * pthread_yield. But that is horribly inefficient. Hence we use only sigwait, no
  * sigtimedwait is available. We need to use another user signal, SIGUSR1. Actually
  * SIGUSR1 is also used by exec in Java. So our usage here breaks the exec in Java,
  * for AIX. You cannot use pthread_cond_wait or pthread_delay_np in the signal
  * handler as all synchronization mechanisms just break down. 
  */

#if defined(PT_NO_SIGTIMEDWAIT)
static void null_signal_handler(PRIntn sig)
{
	return;
}
#endif

static void suspend_signal_handler(PRIntn sig)
{
	PRThread *me = PR_GetCurrentThread();

	PR_ASSERT(me != NULL);
	PR_ASSERT(_PT_IS_GCABLE_THREAD(me));
	PR_ASSERT((me->suspend & PT_THREAD_SUSPENDED) == 0);

	PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
        ("Begin suspend_signal_handler thred %p thread id = %X\n", 
		me, me->id));

	/*
	 * save stack pointer
	 */
	me->sp = &me;

	/* 
	   At this point, the thread's stack pointer has been saved,
	   And it is going to enter a wait loop until it is resumed.
	   So it is _really_ suspended 
	*/

	me->suspend |= PT_THREAD_SUSPENDED;

	/*
	 * now, block current thread
	 */
#if defined(PT_NO_SIGTIMEDWAIT)
	pthread_cond_signal(&me->suspendResumeCV);
	while (me->suspend & PT_THREAD_SUSPENDED)
	{
#if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \
    && !defined(BSDI) && !defined(UNIXWARE) \
    && !defined(DARWIN) && !defined(RISCOS) \
    && !defined(SYMBIAN) /*XXX*/
        PRIntn rv;
	    sigwait(&sigwait_set, &rv);
#endif
	}
	me->suspend |= PT_THREAD_RESUMED;
	pthread_cond_signal(&me->suspendResumeCV);
#else /* defined(PT_NO_SIGTIMEDWAIT) */
	while (me->suspend & PT_THREAD_SUSPENDED)
	{
		PRIntn rv = sigtimedwait(&sigwait_set, NULL, &hundredmillisec);
    	PR_ASSERT(-1 == rv);
	}
	me->suspend |= PT_THREAD_RESUMED;
#endif

    /*
     * At this point, thread has been resumed, so set a global condition.
     * The ResumeAll needs to know that this has really been resumed. 
     * So the signal handler sets a flag which PR_ResumeAll will reset. 
     * The PR_ResumeAll must reset this flag ...
     */

    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
        ("End suspend_signal_handler thred = %p tid = %X\n", me, me->id));
}  /* suspend_signal_handler */

static void pt_SuspendSet(PRThread *thred)
{
    PRIntn rv;

    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
	   ("pt_SuspendSet thred %p thread id = %X\n", thred, thred->id));


    /*
     * Check the thread state and signal the thread to suspend
     */

    PR_ASSERT((thred->suspend & PT_THREAD_SUSPENDED) == 0);

    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
	   ("doing pthread_kill in pt_SuspendSet thred %p tid = %X\n",
	   thred, thred->id));
#if defined(SYMBIAN)
    /* All signal group functions are not implemented in Symbian OS */
    rv = 0;
#else
    rv = pthread_kill (thred->id, SIGUSR2);
#endif
    PR_ASSERT(0 == rv);
}

static void pt_SuspendTest(PRThread *thred)
{
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
	   ("Begin pt_SuspendTest thred %p thread id = %X\n", thred, thred->id));


    /*
     * Wait for the thread to be really suspended. This happens when the
     * suspend signal handler stores the stack pointer and sets the state
     * to suspended. 
     */

#if defined(PT_NO_SIGTIMEDWAIT)
    pthread_mutex_lock(&thred->suspendResumeMutex);
    while ((thred->suspend & PT_THREAD_SUSPENDED) == 0)
    {
	    pthread_cond_timedwait(
	        &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec);
	}
	pthread_mutex_unlock(&thred->suspendResumeMutex);
#else
    while ((thred->suspend & PT_THREAD_SUSPENDED) == 0)
    {
		PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec);
    	PR_ASSERT(-1 == rv);
	}
#endif

    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
        ("End pt_SuspendTest thred %p tid %X\n", thred, thred->id));
}  /* pt_SuspendTest */

static void pt_ResumeSet(PRThread *thred)
{
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
	   ("pt_ResumeSet thred %p thread id = %X\n", thred, thred->id));

    /*
     * Clear the global state and set the thread state so that it will
     * continue past yield loop in the suspend signal handler
     */

    PR_ASSERT(thred->suspend & PT_THREAD_SUSPENDED);


    thred->suspend &= ~PT_THREAD_SUSPENDED;

#if defined(PT_NO_SIGTIMEDWAIT)
#if defined(SYMBIAN) 
	/* All signal group functions are not implemented in Symbian OS */
#else
	pthread_kill(thred->id, SIGUSR1);
#endif
#endif

}  /* pt_ResumeSet */

static void pt_ResumeTest(PRThread *thred)
{
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
	   ("Begin pt_ResumeTest thred %p thread id = %X\n", thred, thred->id));

    /*
     * Wait for the threads resume state to change
     * to indicate it is really resumed 
     */
#if defined(PT_NO_SIGTIMEDWAIT)
    pthread_mutex_lock(&thred->suspendResumeMutex);
    while ((thred->suspend & PT_THREAD_RESUMED) == 0)
    {
	    pthread_cond_timedwait(
	        &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec);
    }
    pthread_mutex_unlock(&thred->suspendResumeMutex);
#else
    while ((thred->suspend & PT_THREAD_RESUMED) == 0) {
		PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec);
    	PR_ASSERT(-1 == rv);
	}
#endif

    thred->suspend &= ~PT_THREAD_RESUMED;

    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, (
        "End pt_ResumeTest thred %p tid %X\n", thred, thred->id));
}  /* pt_ResumeTest */

static pthread_once_t pt_gc_support_control = PTHREAD_ONCE_INIT;

PR_IMPLEMENT(void) PR_SuspendAll(void)
{
#ifdef DEBUG
    PRIntervalTime stime, etime;
#endif
    PRThread* thred = pt_book.first;
    PRThread *me = PR_GetCurrentThread();
    int rv;

    rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support);
    PR_ASSERT(0 == rv);
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
    /*
     * Stop all threads which are marked GC able.
     */
    PR_Lock(pt_book.ml);
#ifdef DEBUG
    suspendAllOn = PR_TRUE;
    stime = PR_IntervalNow();
#endif
    while (thred != NULL)
    {
	    if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
    		pt_SuspendSet(thred);
        thred = thred->next;
    }

    /* Wait till they are really suspended */
    thred = pt_book.first;
    while (thred != NULL)
    {
	    if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
            pt_SuspendTest(thred);
        thred = thred->next;
    }

    suspendAllSuspended = PR_TRUE;

#ifdef DEBUG
    etime = PR_IntervalNow();
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,\
        ("End PR_SuspendAll (time %dms)\n",
        PR_IntervalToMilliseconds(etime - stime)));
#endif
}  /* PR_SuspendAll */

PR_IMPLEMENT(void) PR_ResumeAll(void)
{
#ifdef DEBUG
    PRIntervalTime stime, etime;
#endif
    PRThread* thred = pt_book.first;
    PRThread *me = PR_GetCurrentThread();
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
    /*
     * Resume all previously suspended GC able threads.
     */
    suspendAllSuspended = PR_FALSE;
#ifdef DEBUG
    stime = PR_IntervalNow();
#endif

    while (thred != NULL)
    {
	    if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
    	    pt_ResumeSet(thred);
        thred = thred->next;
    }

    thred = pt_book.first;
    while (thred != NULL)
    {
	    if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
    	    pt_ResumeTest(thred);
        thred = thred->next;
    }

    PR_Unlock(pt_book.ml);
#ifdef DEBUG
    suspendAllOn = PR_FALSE;
    etime = PR_IntervalNow();
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
        ("End PR_ResumeAll (time %dms)\n",
        PR_IntervalToMilliseconds(etime - stime)));
#endif
}  /* PR_ResumeAll */

/* Return the stack pointer for the given thread- used by the GC */
PR_IMPLEMENT(void *)PR_GetSP(PRThread *thred)
{
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
	    ("in PR_GetSP thred %p thid = %X, sp = %p\n", 
	    thred, thred->id, thred->sp));
    return thred->sp;
}  /* PR_GetSP */

#else /* !defined(_PR_DCETHREADS) */

static pthread_once_t pt_gc_support_control = pthread_once_init;

/*
 * For DCE threads, there is no pthread_kill or a way of suspending or resuming a
 * particular thread.  We will just disable the preemption (virtual timer alarm) and
 * let the executing thread finish the garbage collection.  This stops all other threads
 * (GC able or not) and is very inefficient but there is no other choice.
 */
PR_IMPLEMENT(void) PR_SuspendAll()
{
    PRIntn rv;

    rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support);
    PR_ASSERT(0 == rv);  /* returns -1 on failure */
#ifdef DEBUG
    suspendAllOn = PR_TRUE;
#endif
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
    /* 
     * turn off preemption - i.e add virtual alarm signal to the set of 
     * blocking signals 
     */
    rv = sigprocmask(
        SIG_BLOCK, &javagc_vtalarm_sigmask, &javagc_intsoff_sigmask);
    PR_ASSERT(0 == rv);
    suspendAllSuspended = PR_TRUE;
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_SuspendAll\n"));
}  /* PR_SuspendAll */

PR_IMPLEMENT(void) PR_ResumeAll()
{
    PRIntn rv;
    
    suspendAllSuspended = PR_FALSE;
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
    /* turn on preemption - i.e re-enable virtual alarm signal */

    rv = sigprocmask(SIG_SETMASK, &javagc_intsoff_sigmask, (sigset_t *)NULL);
    PR_ASSERT(0 == rv);
#ifdef DEBUG
    suspendAllOn = PR_FALSE;
#endif

    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll\n"));
}  /* PR_ResumeAll */

/* Return the stack pointer for the given thread- used by the GC */
PR_IMPLEMENT(void*)PR_GetSP(PRThread *thred)
{
	pthread_t tid = thred->id;
	char *thread_tcb, *top_sp;

	/*
	 * For HPUX DCE threads, pthread_t is a struct with the
	 * following three fields (see pthread.h, dce/cma.h):
	 *     cma_t_address       field1;
	 *     short int           field2;
	 *     short int           field3;
	 * where cma_t_address is typedef'd to be either void*
	 * or char*.
	 */
	PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n"));
	thread_tcb = (char*)tid.field1;
	top_sp = *(char**)(thread_tcb + 128);
	PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %p \n", top_sp));
	return top_sp;
}  /* PR_GetSP */

#endif /* !defined(_PR_DCETHREADS) */

#endif  /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */

/* ptthread.c */

deps/mozilla/nsprpub/pr/src/threads/


        

deps/mozilla/nsprpub/pr/src/threads/.cvsignore

Makefile

deps/mozilla/nsprpub/pr/src/threads/Makefile.in

# 
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Portable Runtime (NSPR).
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****

#! gmake

MOD_DEPTH	= ../../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(MOD_DEPTH)/config/autoconf.mk

include $(topsrcdir)/config/config.mk

ifdef USE_PTHREADS
    DIRS =
else
ifdef USE_BTHREADS
    DIRS =
else
    DIRS = combined
endif
endif

ifdef USE_PTHREADS
CSRCS = \
	prcmon.c \
	prrwlock.c   \
	prtpd.c \
	$(NULL)
else
ifdef USE_BTHREADS
CSRCS = \
	prcmon.c \
	prrwlock.c   \
	prtpd.c \
	$(NULL)
else
CSRCS =	\
	prcmon.c  \
	prdump.c  \
	prmon.c   \
	prsem.c   \
	prrwlock.c   \
	prcthr.c \
	prtpd.c \
	$(NULL)
endif
endif

TARGETS	= $(OBJS)

INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private

DEFINES	+= -D_NSPR_BUILD_

include $(topsrcdir)/config/rules.mk

export:: $(TARGETS)

deps/mozilla/nsprpub/pr/src/threads/combined/


        

deps/mozilla/nsprpub/pr/src/threads/combined/.cvsignore

Makefile

deps/mozilla/nsprpub/pr/src/threads/combined/Makefile.in

# 
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Portable Runtime (NSPR).
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****


#! gmake

MOD_DEPTH	= ../../../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(MOD_DEPTH)/config/autoconf.mk

include $(topsrcdir)/config/config.mk

# Disable optimization of the nspr on SunOS4.1.3
ifeq ($(OS_ARCH),SunOS)
ifeq ($(OS_RELEASE),4.1.3_U1)
OPTIMIZER =
endif
endif

ifdef USE_PTHREADS
CSRCS =         \
	$(NULL)
else
CSRCS =         \
    prucpu.c      \
	prucv.c      \
	prulock.c    \
	pruthr.c     \
    prustack.c    \
	$(NULL)
endif

TARGETS	= $(OBJS)

INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private

DEFINES	+= -D_NSPR_BUILD_

include $(topsrcdir)/config/rules.mk

export:: $(TARGETS)

deps/mozilla/nsprpub/pr/src/threads/combined/README

NSPR 2.0 evolution
------------------


Phase 1- today

Currently (Oct 10, 1996) NSPR 2.0 has two modes.  Either _PR_NTHREAD 
is defined, in which case the PR_CreateThread() call always creates a 
native kernel thread, or _PR_NTHREAD is not defined and PR_CreateThread() 
always creates user level threads within the single, original process.  This 
source code is reflected in two directories, nspr20/pr/src/threads/native, and 
nspr20/pr/src/threads/user.  Although the PR_CreateThread() function has
a paramter to specify the "scope" of a thread, this parameter is not yet 
used- except on solaris where it uses it to specify bound vs unbound threads.

Phase 2 - next week

The next step is to provide a combination of user and native threads.  The
idea, of course, is to have some small number of native threads and each of 
those threads be able to run user level threads.  The number of native
threads created will most likely be proportional to the number of CPUs in
the system.  For this reason, the specific set of native threads which are
used to run the user-level threads will be called "CPU" threads.  

The user level threads which will be run on the CPU threads are able to
run on any of the CPU threads available, and over the course of a user-level
thread's lifetime, it may drift from one CPU thread to another.  All 
user-level threads will compete for processing time via a single run queue.

Creation of a CPU thread will be primarily controlled by NSPR itself or by
the user running a function PR_Concurrency().  The details of PR_Concurrency()
have not yet been worked out; but the idea is that the user can specify to 
NSPR how many CPU threads are desired.

In this system, user-level threads are created by using PR_CreateThread() and
specifying the PR_LOCAL_SCOPE option.  LOCAL_SCOPE indicates that the thread
will be under the control of the "local" scheduler.  Creating threads with
GLOBAL_SCOPE, on the other hand will create a thread which is under the 
control of the system's scheduler.  In otherwords, this creates a native thread
which is not a CPU thread; it runs a single thread task and never has more 
than one task to run.  LOCAL_SCOPE is much like creating a Solaris unbound 
thread, while GLOBAL_SCOPE is similar to creating a Solaris bound thread.

To implement this architecture, the source code will still maintain the "user"
and "native" directories which is has today.  However a third directory 
"combined" will also exist.  To compile a version of NSPR which only creates
native threads, the user can define _PR_NTHREAD.  For exclusive user-level
threads, do not define _PR_NTHREAD.  To get the combined threads, define
_PR_NTHREAD and _PR_USE_CPUS.


Phase 3 - later than next week

The goal is to eliminate the 3 directories.  Once these three models are in
place, the remaining work will be to eliminate the native and user thread
directories for all platforms, so that the entire thread model is contained
within what is today called the "combined" model.  This new and glorious
source code will attempt to make the "combined" model on any platforms which
provide the necessary underlying native threading, but will also be 
capable of using exclusive user-level threads on systems which don't have
native threads.

deps/mozilla/nsprpub/pr/src/threads/combined/prucpu.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

_PRCPU *_pr_primordialCPU = NULL;

PRInt32 _pr_md_idle_cpus;       /* number of idle cpus */
/*
 * The idle threads in MxN models increment/decrement _pr_md_idle_cpus.
 * If _PR_HAVE_ATOMIC_OPS is not defined, they can't use the atomic
 * increment/decrement routines (which are based on PR_Lock/PR_Unlock),
 * because PR_Lock asserts that the calling thread is not an idle thread.
 * So we use a _MDLock to protect _pr_md_idle_cpus.
 */
#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
#ifndef _PR_HAVE_ATOMIC_OPS
static _MDLock _pr_md_idle_cpus_lock;
#endif
#endif
PRUintn _pr_numCPU;
PRInt32 _pr_cpus_exit;
PRUint32 _pr_cpu_affinity_mask = 0;

#if !defined (_PR_GLOBAL_THREADS_ONLY)

static PRUintn _pr_cpuID;

static void PR_CALLBACK _PR_CPU_Idle(void *);

static _PRCPU *_PR_CreateCPU(void);
static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread);

#if !defined(_PR_LOCAL_THREADS_ONLY)
static void _PR_RunCPU(void *arg);
#endif

void  _PR_InitCPUs()
{
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if (_native_threads_only)
        return;

    _pr_cpuID = 0;
    _MD_NEW_LOCK( &_pr_cpuLock);
#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
#ifndef _PR_HAVE_ATOMIC_OPS
    _MD_NEW_LOCK(&_pr_md_idle_cpus_lock);
#endif
#endif

#ifdef _PR_LOCAL_THREADS_ONLY

#ifdef HAVE_CUSTOM_USER_THREADS
    _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me);
#endif

    /* Now start the first CPU. */
    _pr_primordialCPU = _PR_CreateCPU();
    _pr_numCPU = 1;
    _PR_StartCPU(_pr_primordialCPU, me);

    _PR_MD_SET_CURRENT_CPU(_pr_primordialCPU);

    /* Initialize cpu for current thread (could be different from me) */
    _PR_MD_CURRENT_THREAD()->cpu = _pr_primordialCPU;

    _PR_MD_SET_LAST_THREAD(me);

#else /* Combined MxN model */

    _pr_primordialCPU = _PR_CreateCPU();
    _pr_numCPU = 1;
    _PR_CreateThread(PR_SYSTEM_THREAD,
                     _PR_RunCPU,
                     _pr_primordialCPU,
                     PR_PRIORITY_NORMAL,
                     PR_GLOBAL_THREAD,
                     PR_UNJOINABLE_THREAD,
                     0,
                     _PR_IDLE_THREAD);

#endif /* _PR_LOCAL_THREADS_ONLY */

    _PR_MD_INIT_CPUS();
}

#ifdef WINNT
/*
 * Right now this function merely stops the CPUs and does
 * not do any other cleanup.
 *
 * It is only implemented for WINNT because bug 161998 only
 * affects the WINNT version of NSPR, but it would be nice
 * to implement this function for other platforms too.
 */
void _PR_CleanupCPUs(void)
{
    PRUintn i;
    PRCList *qp;
    _PRCPU *cpu;

    _pr_cpus_exit = 1;
    for (i = 0; i < _pr_numCPU; i++) {
        _PR_MD_WAKEUP_WAITER(NULL);
    }
    for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {
        cpu = _PR_CPU_PTR(qp);
        _PR_MD_JOIN_THREAD(&cpu->thread->md);
    }
}
#endif

static _PRCPUQueue *_PR_CreateCPUQueue(void)
{
    PRInt32 index;
    _PRCPUQueue *cpuQueue;
    cpuQueue = PR_NEWZAP(_PRCPUQueue);
 
    _MD_NEW_LOCK( &cpuQueue->runQLock );
    _MD_NEW_LOCK( &cpuQueue->sleepQLock );
    _MD_NEW_LOCK( &cpuQueue->miscQLock );

    for (index = 0; index < PR_PRIORITY_LAST + 1; index++)
        PR_INIT_CLIST( &(cpuQueue->runQ[index]) );
    PR_INIT_CLIST( &(cpuQueue->sleepQ) );
    PR_INIT_CLIST( &(cpuQueue->pauseQ) );
    PR_INIT_CLIST( &(cpuQueue->suspendQ) );
    PR_INIT_CLIST( &(cpuQueue->waitingToJoinQ) );

    cpuQueue->numCPUs = 1;

    return cpuQueue;
}

/*
 * Create a new CPU.
 *
 * This function initializes enough of the _PRCPU structure so
 * that it can be accessed safely by a global thread or another
 * CPU.  This function does not create the native thread that
 * will run the CPU nor does it initialize the parts of _PRCPU
 * that must be initialized by that native thread.
 *
 * The reason we cannot simply have the native thread create
 * and fully initialize a new CPU is that we need to be able to
 * create a usable _pr_primordialCPU in _PR_InitCPUs without
 * assuming that the primordial CPU thread we created can run
 * during NSPR initialization.  For example, on Windows while
 * new threads can be created by DllMain, they won't be able
 * to run during DLL initialization.  If NSPR is initialized
 * by DllMain, the primordial CPU thread won't run until DLL
 * initialization is finished.
 */
static _PRCPU *_PR_CreateCPU(void)
{
    _PRCPU *cpu;

    cpu = PR_NEWZAP(_PRCPU);
    if (cpu) {
        cpu->queue = _PR_CreateCPUQueue();
        if (!cpu->queue) {
            PR_DELETE(cpu);
            return NULL;
        }
    }
    return cpu;
}

/*
 * Start a new CPU.
 *
 * 'cpu' is a _PRCPU structure created by _PR_CreateCPU().
 * 'thread' is the native thread that will run the CPU.
 *
 * If this function fails, 'cpu' is destroyed.
 */
static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread)
{
    /*
    ** Start a new cpu. The assumption this code makes is that the
    ** underlying operating system creates a stack to go with the new
    ** native thread. That stack will be used by the cpu when pausing.
    */

    PR_ASSERT(!_native_threads_only);

    cpu->last_clock = PR_IntervalNow();

    /* Before we create any threads on this CPU we have to
     * set the current CPU 
     */
    _PR_MD_SET_CURRENT_CPU(cpu);
    _PR_MD_INIT_RUNNING_CPU(cpu);
    thread->cpu = cpu;

    cpu->idle_thread = _PR_CreateThread(PR_SYSTEM_THREAD,
                                        _PR_CPU_Idle,
                                        (void *)cpu,
                                        PR_PRIORITY_NORMAL,
                                        PR_LOCAL_THREAD,
                                        PR_UNJOINABLE_THREAD,
                                        0,
                                        _PR_IDLE_THREAD);

    if (!cpu->idle_thread) {
        /* didn't clean up CPU queue XXXMB */
        PR_DELETE(cpu);
        return PR_FAILURE;
    } 
    PR_ASSERT(cpu->idle_thread->cpu == cpu);

    cpu->idle_thread->no_sched = 0;

    cpu->thread = thread;

    if (_pr_cpu_affinity_mask)
        PR_SetThreadAffinityMask(thread, _pr_cpu_affinity_mask);

    /* Created and started a new CPU */
    _PR_CPU_LIST_LOCK();
    cpu->id = _pr_cpuID++;
    PR_APPEND_LINK(&cpu->links, &_PR_CPUQ());
    _PR_CPU_LIST_UNLOCK();

    return PR_SUCCESS;
}

#if !defined(_PR_GLOBAL_THREADS_ONLY) && !defined(_PR_LOCAL_THREADS_ONLY)
/*
** This code is used during a cpu's initial creation.
*/
static void _PR_RunCPU(void *arg)
{
    _PRCPU *cpu = (_PRCPU *)arg;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT(NULL != me);

    /*
     * _PR_StartCPU calls _PR_CreateThread to create the
     * idle thread.  Because _PR_CreateThread calls PR_Lock,
     * the current thread has to remain a global thread
     * during the _PR_StartCPU call so that it can wait for
     * the lock if the lock is held by another thread.  If
     * we clear the _PR_GLOBAL_SCOPE flag in
     * _PR_MD_CREATE_PRIMORDIAL_THREAD, the current thread
     * will be treated as a local thread and have trouble
     * waiting for the lock because the CPU is not fully
     * constructed yet.
     *
     * After the CPU is started, it is safe to mark the
     * current thread as a local thread.
     */

#ifdef HAVE_CUSTOM_USER_THREADS
    _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me);
#endif

    me->no_sched = 1;
    _PR_StartCPU(cpu, me);

#ifdef HAVE_CUSTOM_USER_THREADS
    me->flags &= (~_PR_GLOBAL_SCOPE);
#endif

    _PR_MD_SET_CURRENT_CPU(cpu);
    _PR_MD_SET_CURRENT_THREAD(cpu->thread);
    me->cpu = cpu;

    while(1) {
        PRInt32 is;
        if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
	    _PR_MD_START_INTERRUPTS();
        _PR_MD_SWITCH_CONTEXT(me);
    }
}
#endif

static void PR_CALLBACK _PR_CPU_Idle(void *_cpu)
{
    _PRCPU *cpu = (_PRCPU *)_cpu;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT(NULL != me);

    me->cpu = cpu;
    cpu->idle_thread = me;
    if (_MD_LAST_THREAD())
        _MD_LAST_THREAD()->no_sched = 0;
    if (!_PR_IS_NATIVE_THREAD(me)) _PR_MD_SET_INTSOFF(0);
    while(1) {
        PRInt32 is;
        PRIntervalTime timeout;
        if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);

        _PR_RUNQ_LOCK(cpu);
#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
#ifdef _PR_HAVE_ATOMIC_OPS
        _PR_MD_ATOMIC_INCREMENT(&_pr_md_idle_cpus);
#else
        _PR_MD_LOCK(&_pr_md_idle_cpus_lock);
        _pr_md_idle_cpus++;
        _PR_MD_UNLOCK(&_pr_md_idle_cpus_lock);
#endif /* _PR_HAVE_ATOMIC_OPS */
#endif
        /* If someone on runq; do a nonblocking PAUSECPU */
        if (_PR_RUNQREADYMASK(me->cpu) != 0) {
            _PR_RUNQ_UNLOCK(cpu);
            timeout = PR_INTERVAL_NO_WAIT;
        } else {
            _PR_RUNQ_UNLOCK(cpu);

            _PR_SLEEPQ_LOCK(cpu);
            if (PR_CLIST_IS_EMPTY(&_PR_SLEEPQ(me->cpu))) {
                timeout = PR_INTERVAL_NO_TIMEOUT;
            } else {
                PRThread *wakeThread;
                wakeThread = _PR_THREAD_PTR(_PR_SLEEPQ(me->cpu).next);
                timeout = wakeThread->sleep;
            }
            _PR_SLEEPQ_UNLOCK(cpu);
        }

        /* Wait for an IO to complete */
        (void)_PR_MD_PAUSE_CPU(timeout);

#ifdef WINNT
        if (_pr_cpus_exit) {
            /* _PR_CleanupCPUs tells us to exit */
            _PR_MD_END_THREAD();
        }
#endif

#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
#ifdef _PR_HAVE_ATOMIC_OPS
        _PR_MD_ATOMIC_DECREMENT(&_pr_md_idle_cpus);
#else
        _PR_MD_LOCK(&_pr_md_idle_cpus_lock);
        _pr_md_idle_cpus--;
        _PR_MD_UNLOCK(&_pr_md_idle_cpus_lock);
#endif /* _PR_HAVE_ATOMIC_OPS */
#endif

		_PR_ClockInterrupt();

		/* Now schedule any thread that is on the runq
		 * INTS must be OFF when calling PR_Schedule()
		 */
		me->state = _PR_RUNNABLE;
		_PR_MD_SWITCH_CONTEXT(me);
		if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is);
    }
}
#endif /* _PR_GLOBAL_THREADS_ONLY */

PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs)
{
#if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_LOCAL_THREADS_ONLY)

    /* do nothing */

#else /* combined, MxN thread model */

    PRUintn newCPU;
    _PRCPU *cpu;
    PRThread *thr;


    if (!_pr_initialized) _PR_ImplicitInitialization();

	if (_native_threads_only)
		return;
    
    _PR_CPU_LIST_LOCK();
    if (_pr_numCPU < numCPUs) {
        newCPU = numCPUs - _pr_numCPU;
        _pr_numCPU = numCPUs;
    } else newCPU = 0;
    _PR_CPU_LIST_UNLOCK();

    for (; newCPU; newCPU--) {
        cpu = _PR_CreateCPU();
        thr = _PR_CreateThread(PR_SYSTEM_THREAD,
                              _PR_RunCPU,
                              cpu,
                              PR_PRIORITY_NORMAL,
                              PR_GLOBAL_THREAD,
                              PR_UNJOINABLE_THREAD,
                              0,
                              _PR_IDLE_THREAD);
    }
#endif
}

PR_IMPLEMENT(_PRCPU *) _PR_GetPrimordialCPU(void)
{
    if (_pr_primordialCPU)
        return _pr_primordialCPU;
    else
        return _PR_MD_CURRENT_CPU();
}

deps/mozilla/nsprpub/pr/src/threads/combined/prucv.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */


#include "primpl.h"
#include "prinrval.h"
#include "prtypes.h"

#if defined(WIN95)
/*
** Some local variables report warnings on Win95 because the code paths 
** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
** The pragma suppresses the warning.
** 
*/
#pragma warning(disable : 4101)
#endif


/*
** Notify one thread that it has finished waiting on a condition variable
** Caller must hold the _PR_CVAR_LOCK(cv)
*/
PRBool _PR_NotifyThread (PRThread *thread, PRThread *me)
{
    PRBool rv;

    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);

    _PR_THREAD_LOCK(thread);
    PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
    if ( !_PR_IS_NATIVE_THREAD(thread) ) {
        if (thread->wait.cvar != NULL) {
            thread->wait.cvar = NULL;

            _PR_SLEEPQ_LOCK(thread->cpu);
            /* The notify and timeout can collide; in which case both may
             * attempt to delete from the sleepQ; only let one do it.
             */
            if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ))
                _PR_DEL_SLEEPQ(thread, PR_TRUE);
            _PR_SLEEPQ_UNLOCK(thread->cpu);

	    if (thread->flags & _PR_SUSPENDING) {
		/*
		 * set thread state to SUSPENDED; a Resume operation
		 * on the thread will move it to the runQ
		 */
            	thread->state = _PR_SUSPENDED;
		_PR_MISCQ_LOCK(thread->cpu);
		_PR_ADD_SUSPENDQ(thread, thread->cpu);
		_PR_MISCQ_UNLOCK(thread->cpu);
            	_PR_THREAD_UNLOCK(thread);
	    } else {
            	/* Make thread runnable */
            	thread->state = _PR_RUNNABLE;
            	_PR_THREAD_UNLOCK(thread);

                _PR_AddThreadToRunQ(me, thread);
                _PR_MD_WAKEUP_WAITER(thread);
            }

            rv = PR_TRUE;
        } else {
            /* Thread has already been notified */
            _PR_THREAD_UNLOCK(thread);
            rv = PR_FALSE;
        }
    } else { /* If the thread is a native thread */
        if (thread->wait.cvar) {
            thread->wait.cvar = NULL;

	    if (thread->flags & _PR_SUSPENDING) {
		/*
		 * set thread state to SUSPENDED; a Resume operation
		 * on the thread will enable the thread to run
		 */
            	thread->state = _PR_SUSPENDED;
	     } else
            	thread->state = _PR_RUNNING;
            _PR_THREAD_UNLOCK(thread);
            _PR_MD_WAKEUP_WAITER(thread);
            rv = PR_TRUE;
        } else {
            _PR_THREAD_UNLOCK(thread);
            rv = PR_FALSE;
        }    
    }    

    return rv;
}

/*
 * Notify thread waiting on cvar; called when thread is interrupted
 * 	The thread lock is held on entry and released before return
 */
void _PR_NotifyLockedThread (PRThread *thread)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRCondVar *cvar;
    PRThreadPriority pri;

    if ( !_PR_IS_NATIVE_THREAD(me))
    	PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);

    cvar = thread->wait.cvar;
    thread->wait.cvar = NULL;
    _PR_THREAD_UNLOCK(thread);

    _PR_CVAR_LOCK(cvar);
    _PR_THREAD_LOCK(thread);

    if (!_PR_IS_NATIVE_THREAD(thread)) {
            _PR_SLEEPQ_LOCK(thread->cpu);
            /* The notify and timeout can collide; in which case both may
             * attempt to delete from the sleepQ; only let one do it.
             */
            if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ))
                _PR_DEL_SLEEPQ(thread, PR_TRUE);
            _PR_SLEEPQ_UNLOCK(thread->cpu);

	    /* Make thread runnable */
	    pri = thread->priority;
	    thread->state = _PR_RUNNABLE;

	    PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));

            _PR_AddThreadToRunQ(me, thread);
            _PR_THREAD_UNLOCK(thread);

            _PR_MD_WAKEUP_WAITER(thread);
    } else {
	    if (thread->flags & _PR_SUSPENDING) {
		/*
		 * set thread state to SUSPENDED; a Resume operation
		 * on the thread will enable the thread to run
		 */
            	thread->state = _PR_SUSPENDED;
	     } else
            	thread->state = _PR_RUNNING;
            _PR_THREAD_UNLOCK(thread);
            _PR_MD_WAKEUP_WAITER(thread);
    }    

    _PR_CVAR_UNLOCK(cvar);
    return;
}

/*
** Make the given thread wait for the given condition variable
*/
PRStatus _PR_WaitCondVar(
    PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout)
{
    PRIntn is;
    PRStatus rv = PR_SUCCESS;

    PR_ASSERT(thread == _PR_MD_CURRENT_THREAD());
    PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));

#ifdef _PR_GLOBAL_THREADS_ONLY
    if (_PR_PENDING_INTERRUPT(thread)) {
        PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        thread->flags &= ~_PR_INTERRUPT;
        return PR_FAILURE;
    }

    thread->wait.cvar = cvar;
    lock->owner = NULL;
    _PR_MD_WAIT_CV(&cvar->md,&lock->ilock, timeout);
    thread->wait.cvar = NULL;
    lock->owner = thread;
    if (_PR_PENDING_INTERRUPT(thread)) {
        PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        thread->flags &= ~_PR_INTERRUPT;
        return PR_FAILURE;
    }

    return PR_SUCCESS;
#else  /* _PR_GLOBAL_THREADS_ONLY */

    if ( !_PR_IS_NATIVE_THREAD(thread))
    	_PR_INTSOFF(is);

    _PR_CVAR_LOCK(cvar);
    _PR_THREAD_LOCK(thread);

    if (_PR_PENDING_INTERRUPT(thread)) {
        PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        thread->flags &= ~_PR_INTERRUPT;
    	_PR_CVAR_UNLOCK(cvar);
    	_PR_THREAD_UNLOCK(thread);
    	if ( !_PR_IS_NATIVE_THREAD(thread))
    		_PR_INTSON(is);
        return PR_FAILURE;
    }

    thread->state = _PR_COND_WAIT;
    thread->wait.cvar = cvar;

    /*
    ** Put the caller thread on the condition variable's wait Q
    */
    PR_APPEND_LINK(&thread->waitQLinks, &cvar->condQ);

    /* Note- for global scope threads, we don't put them on the
     *       global sleepQ, so each global thread must put itself
     *       to sleep only for the time it wants to.
     */
    if ( !_PR_IS_NATIVE_THREAD(thread) ) {
        _PR_SLEEPQ_LOCK(thread->cpu);
        _PR_ADD_SLEEPQ(thread, timeout);
        _PR_SLEEPQ_UNLOCK(thread->cpu);
    }
    _PR_CVAR_UNLOCK(cvar);
    _PR_THREAD_UNLOCK(thread);
   
    /* 
    ** Release lock protecting the condition variable and thereby giving time 
    ** to the next thread which can potentially notify on the condition variable
    */
    PR_Unlock(lock);

    PR_LOG(_pr_cvar_lm, PR_LOG_MIN,
	   ("PR_Wait: cvar=%p waiting for %d", cvar, timeout));

    rv = _PR_MD_WAIT(thread, timeout);

    _PR_CVAR_LOCK(cvar);
    PR_REMOVE_LINK(&thread->waitQLinks);
    _PR_CVAR_UNLOCK(cvar);

    PR_LOG(_pr_cvar_lm, PR_LOG_MIN,
	   ("PR_Wait: cvar=%p done waiting", cvar));

    if ( !_PR_IS_NATIVE_THREAD(thread))
    	_PR_INTSON(is);

    /* Acquire lock again that we had just relinquished */
    PR_Lock(lock);

    if (_PR_PENDING_INTERRUPT(thread)) {
        PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        thread->flags &= ~_PR_INTERRUPT;
        return PR_FAILURE;
    }

    return rv;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me)
{
#ifdef _PR_GLOBAL_THREADS_ONLY
    _PR_MD_NOTIFY_CV(&cvar->md, &cvar->lock->ilock);
#else  /* _PR_GLOBAL_THREADS_ONLY */

    PRCList *q;
    PRIntn is;

    if ( !_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSOFF(is);
    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);

    _PR_CVAR_LOCK(cvar);
    q = cvar->condQ.next;
    while (q != &cvar->condQ) {
        PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("_PR_NotifyCondVar: cvar=%p", cvar));
        if (_PR_THREAD_CONDQ_PTR(q)->wait.cvar)  {
            if (_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me) == PR_TRUE)
                break;
        }
        q = q->next;
    }
    _PR_CVAR_UNLOCK(cvar);

    if ( !_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSON(is);

#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

/*
** Cndition variable debugging log info.
*/
PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen)
{
    PRUint32 nb;

    if (cvar->lock->owner) {
	nb = PR_snprintf(buf, buflen, "[%p] owner=%ld[%p]",
			 cvar, cvar->lock->owner->id, cvar->lock->owner);
    } else {
	nb = PR_snprintf(buf, buflen, "[%p]", cvar);
    }
    return nb;
}

/*
** Expire condition variable waits that are ready to expire. "now" is the current
** time.
*/
void _PR_ClockInterrupt(void)
{
    PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
    _PRCPU *cpu = me->cpu;
    PRIntervalTime elapsed, now;
 
    PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
    /* Figure out how much time elapsed since the last clock tick */
    now = PR_IntervalNow();
    elapsed = now - cpu->last_clock;
    cpu->last_clock = now;

    PR_LOG(_pr_clock_lm, PR_LOG_MAX,
	   ("ExpireWaits: elapsed=%lld usec", elapsed));

    while(1) {
        _PR_SLEEPQ_LOCK(cpu);
        if (_PR_SLEEPQ(cpu).next == &_PR_SLEEPQ(cpu)) {
            _PR_SLEEPQ_UNLOCK(cpu);
            break;
        }

        thread = _PR_THREAD_PTR(_PR_SLEEPQ(cpu).next);
        PR_ASSERT(thread->cpu == cpu);

        if (elapsed < thread->sleep) {
            thread->sleep -= elapsed;
            _PR_SLEEPQMAX(thread->cpu) -= elapsed;
            _PR_SLEEPQ_UNLOCK(cpu);
            break;
        }
        _PR_SLEEPQ_UNLOCK(cpu);

        PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));

        _PR_THREAD_LOCK(thread);

        if (thread->cpu != cpu) {
            /*
            ** The thread was switched to another CPU
            ** between the time we unlocked the sleep
            ** queue and the time we acquired the thread
            ** lock, so it is none of our business now.
            */
            _PR_THREAD_UNLOCK(thread);
            continue;
        }

        /*
        ** Consume this sleeper's amount of elapsed time from the elapsed
        ** time value. The next remaining piece of elapsed time will be
        ** available for the next sleeping thread's timer.
        */
        _PR_SLEEPQ_LOCK(cpu);
        PR_ASSERT(!(thread->flags & _PR_ON_PAUSEQ));
        if (thread->flags & _PR_ON_SLEEPQ) {
            _PR_DEL_SLEEPQ(thread, PR_FALSE);
            elapsed -= thread->sleep;
            _PR_SLEEPQ_UNLOCK(cpu);
        } else {
            /* Thread was already handled; Go get another one */
            _PR_SLEEPQ_UNLOCK(cpu);
            _PR_THREAD_UNLOCK(thread);
            continue;
        }

        /* Notify the thread waiting on the condition variable */
        if (thread->flags & _PR_SUSPENDING) {
		PR_ASSERT((thread->state == _PR_IO_WAIT) ||
				(thread->state == _PR_COND_WAIT));
            /*
            ** Thread is suspended and its condition timeout
            ** expired. Transfer thread from sleepQ to suspendQ.
            */
            thread->wait.cvar = NULL;
            _PR_MISCQ_LOCK(cpu);
            thread->state = _PR_SUSPENDED;
            _PR_ADD_SUSPENDQ(thread, cpu);
            _PR_MISCQ_UNLOCK(cpu);
        } else {
            if (thread->wait.cvar) {
                PRThreadPriority pri;

                /* Do work very similar to what _PR_NotifyThread does */
                PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );

                /* Make thread runnable */
                pri = thread->priority;
                thread->state = _PR_RUNNABLE;
                PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));

                PR_ASSERT(thread->cpu == cpu);
                _PR_RUNQ_LOCK(cpu);
                _PR_ADD_RUNQ(thread, cpu, pri);
                _PR_RUNQ_UNLOCK(cpu);

                if (pri > me->priority)
                    _PR_SET_RESCHED_FLAG();

                thread->wait.cvar = NULL;

                _PR_MD_WAKEUP_WAITER(thread);

            } else if (thread->io_pending == PR_TRUE) {
                /* Need to put IO sleeper back on runq */
                int pri = thread->priority;

                thread->io_suspended = PR_TRUE;
#ifdef WINNT
				/*
				 * For NT, record the cpu on which I/O was issued
				 * I/O cancellation is done on the same cpu
				 */
                thread->md.thr_bound_cpu = cpu;
#endif

				PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
                PR_ASSERT(thread->cpu == cpu);
                thread->state = _PR_RUNNABLE;
                _PR_RUNQ_LOCK(cpu);
                _PR_ADD_RUNQ(thread, cpu, pri);
                _PR_RUNQ_UNLOCK(cpu);
            }
        }
        _PR_THREAD_UNLOCK(thread);
    }
}

/************************************************************************/

/*
** Create a new condition variable.
** 	"lock" is the lock to use with the condition variable.
**
** Condition variables are synchronization objects that threads can use
** to wait for some condition to occur.
**
** This may fail if memory is tight or if some operating system resource
** is low.
*/
PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
{
    PRCondVar *cvar;

    PR_ASSERT(lock != NULL);

    cvar = PR_NEWZAP(PRCondVar);
    if (cvar) {
#ifdef _PR_GLOBAL_THREADS_ONLY
	if(_PR_MD_NEW_CV(&cvar->md)) {
		PR_DELETE(cvar);
		PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
		return NULL;
	}
#endif
        if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE) {
		PR_DELETE(cvar);
		PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
		return NULL;
	}
    cvar->lock = lock;
	PR_INIT_CLIST(&cvar->condQ);

    } else {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    }
    return cvar;
}

/*
** Destroy a condition variable. There must be no thread
** waiting on the condvar. The caller is responsible for guaranteeing
** that the condvar is no longer in use.
**
*/
PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
{
    PR_ASSERT(cvar->condQ.next == &cvar->condQ);

#ifdef _PR_GLOBAL_THREADS_ONLY
    _PR_MD_FREE_CV(&cvar->md);
#endif
    _PR_MD_FREE_LOCK(&(cvar->ilock));
 
    PR_DELETE(cvar);
}

/*
** Wait for a notify on the condition variable. Sleep for "tiemout" amount
** of ticks (if "timeout" is zero then the sleep is indefinite). While
** the thread is waiting it unlocks lock. When the wait has
** finished the thread regains control of the condition variable after
** locking the associated lock.
**
** The thread waiting on the condvar will be resumed when the condvar is
** notified (assuming the thread is the next in line to receive the
** notify) or when the timeout elapses.
**
** Returns PR_FAILURE if the caller has not locked the lock associated
** with the condition variable or the thread has been interrupted.
*/
extern PRThread *suspendAllThread;
PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();

	PR_ASSERT(cvar->lock->owner == me);
	PR_ASSERT(me != suspendAllThread);
    	if (cvar->lock->owner != me) return PR_FAILURE;

	return _PR_WaitCondVar(me, cvar, cvar->lock, timeout);
}

/*
** Notify the highest priority thread waiting on the condition
** variable. If a thread is waiting on the condition variable (using
** PR_Wait) then it is awakened and begins waiting on the lock.
*/
PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT(cvar->lock->owner == me);
    PR_ASSERT(me != suspendAllThread);
    if (cvar->lock->owner != me) return PR_FAILURE;

    _PR_NotifyCondVar(cvar, me);
    return PR_SUCCESS;
}

/*
** Notify all of the threads waiting on the condition variable. All of
** threads are notified in turn. The highest priority thread will
** probably acquire the lock.
*/
PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
{
    PRCList *q;
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT(cvar->lock->owner == me);
    if (cvar->lock->owner != me) return PR_FAILURE;

#ifdef _PR_GLOBAL_THREADS_ONLY
    _PR_MD_NOTIFYALL_CV(&cvar->md, &cvar->lock->ilock);
    return PR_SUCCESS;
#else  /* _PR_GLOBAL_THREADS_ONLY */
    if ( !_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSOFF(is);
    _PR_CVAR_LOCK(cvar);
    q = cvar->condQ.next;
    while (q != &cvar->condQ) {
		PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
		_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
		q = q->next;
    }
    _PR_CVAR_UNLOCK(cvar);
    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSON(is);

    return PR_SUCCESS;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}


/*********************************************************************/
/*********************************************************************/
/********************ROUTINES FOR DCE EMULATION***********************/
/*********************************************************************/
/*********************************************************************/
#include "prpdce.h"

PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
{
    PRCondVar *cvar = PR_NEWZAP(PRCondVar);
    if (NULL != cvar)
    {
        if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE)
        {
		    PR_DELETE(cvar); cvar = NULL;
	    }
	    else
	    {
	        PR_INIT_CLIST(&cvar->condQ);
            cvar->lock = _PR_NAKED_CV_LOCK;
	    }

    }
    return cvar;
}

PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar)
{
    PR_ASSERT(cvar->condQ.next == &cvar->condQ);
    PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);

    _PR_MD_FREE_LOCK(&(cvar->ilock));
 
    PR_DELETE(cvar);
}

PR_IMPLEMENT(PRStatus) PRP_NakedWait(
	PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
	return _PR_WaitCondVar(me, cvar, lock, timeout);
}  /* PRP_NakedWait */

PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);

    _PR_NotifyCondVar(cvar, me);

    return PR_SUCCESS;
}  /* PRP_NakedNotify */

PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar)
{
    PRCList *q;
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);

    if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
	_PR_MD_LOCK( &(cvar->ilock) );
    q = cvar->condQ.next;
    while (q != &cvar->condQ) {
		PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
		_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
		q = q->next;
    }
	_PR_MD_UNLOCK( &(cvar->ilock) );
    if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);

    return PR_SUCCESS;
}  /* PRP_NakedBroadcast */

deps/mozilla/nsprpub/pr/src/threads/combined/prulock.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

#if defined(WIN95)
/*
** Some local variables report warnings on Win95 because the code paths 
** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
** The pragma suppresses the warning.
** 
*/
#pragma warning(disable : 4101)
#endif


void _PR_InitLocks(void)
{
	_PR_MD_INIT_LOCKS();
}

/*
** Deal with delayed interrupts/requested reschedule during interrupt
** re-enables.
*/
void _PR_IntsOn(_PRCPU *cpu)
{
    PRUintn missed, pri, i;
    _PRInterruptTable *it;
    PRThread *me;

    PR_ASSERT(cpu);   /* Global threads don't have CPUs */
    PR_ASSERT(_PR_MD_GET_INTSOFF() > 0);
	me = _PR_MD_CURRENT_THREAD();
    PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));

    /*
    ** Process delayed interrupts. This logic is kinda scary because we
    ** need to avoid losing an interrupt (it's ok to delay an interrupt
    ** until later).
    **
    ** There are two missed state words. _pr_ints.where indicates to the
    ** interrupt handler which state word is currently safe for
    ** modification.
    **
    ** This code scans both interrupt state words, using the where flag
    ** to indicate to the interrupt which state word is safe for writing.
    ** If an interrupt comes in during a scan the other word will be
    ** modified. This modification will be noticed during the next
    ** iteration of the loop or during the next call to this routine.
    */
    for (i = 0; i < 2; i++) {
        cpu->where = (1 - i);
        missed = cpu->u.missed[i];
        if (missed != 0) {
            cpu->u.missed[i] = 0;
            for (it = _pr_interruptTable; it->name; it++) {
                if (missed & it->missed_bit) {
                    PR_LOG(_pr_sched_lm, PR_LOG_MIN,
                           ("IntsOn[0]: %s intr", it->name));
                    (*it->handler)();
                }
            }
        }
    }

    if (cpu->u.missed[3] != 0) {
        _PRCPU *cpu;

		_PR_THREAD_LOCK(me);
        me->state = _PR_RUNNABLE;
        pri = me->priority;

        cpu = me->cpu;
		_PR_RUNQ_LOCK(cpu);
        _PR_ADD_RUNQ(me, cpu, pri);
		_PR_RUNQ_UNLOCK(cpu);
		_PR_THREAD_UNLOCK(me);
        _PR_MD_SWITCH_CONTEXT(me);
    }
}

/*
** Unblock the first runnable waiting thread. Skip over
** threads that are trying to be suspended
** Note: Caller must hold _PR_LOCK_LOCK()
*/
void _PR_UnblockLockWaiter(PRLock *lock)
{
    PRThread *t = NULL;
    PRThread *me;
    PRCList *q;

    q = lock->waitQ.next;
    PR_ASSERT(q != &lock->waitQ);
    while (q != &lock->waitQ) {
        /* Unblock first waiter */
        t = _PR_THREAD_CONDQ_PTR(q);

		/* 
		** We are about to change the thread's state to runnable and for local
		** threads, we are going to assign a cpu to it.  So, protect thread's
		** data structure.
		*/
        _PR_THREAD_LOCK(t);

        if (t->flags & _PR_SUSPENDING) {
            q = q->next;
            _PR_THREAD_UNLOCK(t);
            continue;
        }

        /* Found a runnable thread */
	    PR_ASSERT(t->state == _PR_LOCK_WAIT);
	    PR_ASSERT(t->wait.lock == lock);
        t->wait.lock = 0;
        PR_REMOVE_LINK(&t->waitQLinks);         /* take it off lock's waitQ */

		/*
		** If this is a native thread, nothing else to do except to wake it
		** up by calling the machine dependent wakeup routine.
		**
		** If this is a local thread, we need to assign it a cpu and
		** put the thread on that cpu's run queue.  There are two cases to
		** take care of.  If the currently running thread is also a local
		** thread, we just assign our own cpu to that thread and put it on
		** the cpu's run queue.  If the the currently running thread is a
		** native thread, we assign the primordial cpu to it (on NT,
		** MD_WAKEUP handles the cpu assignment).  
		*/
		
        if ( !_PR_IS_NATIVE_THREAD(t) ) {

            t->state = _PR_RUNNABLE;

            me = _PR_MD_CURRENT_THREAD();

            _PR_AddThreadToRunQ(me, t);
            _PR_THREAD_UNLOCK(t);
        } else {
            t->state = _PR_RUNNING;
            _PR_THREAD_UNLOCK(t);
        }
        _PR_MD_WAKEUP_WAITER(t);
        break;
    }
    return;
}

/************************************************************************/


PR_IMPLEMENT(PRLock*) PR_NewLock(void)
{
    PRLock *lock;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    lock = PR_NEWZAP(PRLock);
    if (lock) {
        if (_PR_MD_NEW_LOCK(&lock->ilock) == PR_FAILURE) {
		PR_DELETE(lock);
		return(NULL);
	}
        PR_INIT_CLIST(&lock->links);
        PR_INIT_CLIST(&lock->waitQ);
    }
    return lock;
}

/*
** Destroy the given lock "lock". There is no point in making this race
** free because if some other thread has the pointer to this lock all
** bets are off.
*/
PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
{
    PR_ASSERT(lock->owner == 0);
	_PR_MD_FREE_LOCK(&lock->ilock);
    PR_DELETE(lock);
}

extern PRThread *suspendAllThread;
/*
** Lock the lock.
*/
PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRIntn is;
    PRThread *t;
    PRCList *q;

    PR_ASSERT(me != suspendAllThread); 
    PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
    PR_ASSERT(lock != NULL);
#ifdef _PR_GLOBAL_THREADS_ONLY 
    PR_ASSERT(lock->owner != me);
    _PR_MD_LOCK(&lock->ilock);
    lock->owner = me;
    return;
#else  /* _PR_GLOBAL_THREADS_ONLY */

	if (_native_threads_only) {
		PR_ASSERT(lock->owner != me);
		_PR_MD_LOCK(&lock->ilock);
		lock->owner = me;
		return;
	}

    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSOFF(is);

    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);

retry:
    _PR_LOCK_LOCK(lock);
    if (lock->owner == 0) {
        /* Just got the lock */
        lock->owner = me;
        lock->priority = me->priority;
		/* Add the granted lock to this owning thread's lock list */
        PR_APPEND_LINK(&lock->links, &me->lockList);
        _PR_LOCK_UNLOCK(lock);
    	if (!_PR_IS_NATIVE_THREAD(me))
        	_PR_FAST_INTSON(is);
        return;
    }

    /* If this thread already owns this lock, then it is a deadlock */
    PR_ASSERT(lock->owner != me);

    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);

#if 0
    if (me->priority > lock->owner->priority) {
        /*
        ** Give the lock owner a priority boost until we get the
        ** lock. Record the priority we boosted it to.
        */
        lock->boostPriority = me->priority;
        _PR_SetThreadPriority(lock->owner, me->priority);
    }
#endif

    /* 
    Add this thread to the asked for lock's list of waiting threads.  We
    add this thread thread in the right priority order so when the unlock
    occurs, the thread with the higher priority will get the lock.
    */
    q = lock->waitQ.next;
    if (q == &lock->waitQ || _PR_THREAD_CONDQ_PTR(q)->priority ==
      	_PR_THREAD_CONDQ_PTR(lock->waitQ.prev)->priority) {
		/*
		 * If all the threads in the lock waitQ have the same priority,
		 * then avoid scanning the list:  insert the element at the end.
		 */
		q = &lock->waitQ;
    } else {
		/* Sort thread into lock's waitQ at appropriate point */
		/* Now scan the list for where to insert this entry */
		while (q != &lock->waitQ) {
			t = _PR_THREAD_CONDQ_PTR(lock->waitQ.next);
			if (me->priority > t->priority) {
				/* Found a lower priority thread to insert in front of */
				break;
			}
			q = q->next;
		}
	}
    PR_INSERT_BEFORE(&me->waitQLinks, q);

	/* 
	Now grab the threadLock since we are about to change the state.  We have
	to do this since a PR_Suspend or PR_SetThreadPriority type call that takes
	a PRThread* as an argument could be changing the state of this thread from
	a thread running on a different cpu.
	*/

    _PR_THREAD_LOCK(me);
    me->state = _PR_LOCK_WAIT;
    me->wait.lock = lock;
    _PR_THREAD_UNLOCK(me);

    _PR_LOCK_UNLOCK(lock);

    _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
	goto retry;

#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

/*
** Unlock the lock.
*/
PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
{
    PRCList *q;
    PRThreadPriority pri, boost;
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT(lock != NULL);
    PR_ASSERT(lock->owner == me);
    PR_ASSERT(me != suspendAllThread); 
    PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
    if (lock->owner != me) {
        return PR_FAILURE;
    }

#ifdef _PR_GLOBAL_THREADS_ONLY 
    lock->owner = 0;
    _PR_MD_UNLOCK(&lock->ilock);
    return PR_SUCCESS;
#else  /* _PR_GLOBAL_THREADS_ONLY */

	if (_native_threads_only) {
		lock->owner = 0;
		_PR_MD_UNLOCK(&lock->ilock);
		return PR_SUCCESS;
	}

    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSOFF(is);
    _PR_LOCK_LOCK(lock);

	/* Remove the lock from the owning thread's lock list */
    PR_REMOVE_LINK(&lock->links);
    pri = lock->priority;
    boost = lock->boostPriority;
    if (boost > pri) {
        /*
        ** We received a priority boost during the time we held the lock.
        ** We need to figure out what priority to move to by scanning
        ** down our list of lock's that we are still holding and using
        ** the highest boosted priority found.
        */
        q = me->lockList.next;
        while (q != &me->lockList) {
            PRLock *ll = _PR_LOCK_PTR(q);
            if (ll->boostPriority > pri) {
                pri = ll->boostPriority;
            }
            q = q->next;
        }
        if (pri != me->priority) {
            _PR_SetThreadPriority(me, pri);
        }
    }

    /* Unblock the first waiting thread */
    q = lock->waitQ.next;
    if (q != &lock->waitQ)
        _PR_UnblockLockWaiter(lock);
    lock->boostPriority = PR_PRIORITY_LOW;
    lock->owner = 0;
    _PR_LOCK_UNLOCK(lock);
    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSON(is);
    return PR_SUCCESS;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

/*
**  If the current thread owns |lock|, this assertion is guaranteed to
**  succeed.  Otherwise, the behavior of this function is undefined.
*/
PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PR_ASSERT(lock->owner == me);
}

/*
** Test and then lock the lock if it's not already locked by some other
** thread. Return PR_FALSE if some other thread owned the lock at the
** time of the call.
*/
PR_IMPLEMENT(PRBool) PR_TestAndLock(PRLock *lock)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRBool rv = PR_FALSE;
    PRIntn is;

#ifdef _PR_GLOBAL_THREADS_ONLY 
    is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
    if (is == 0) {
        lock->owner = me;
        return PR_TRUE;
    }
    return PR_FALSE;
#else  /* _PR_GLOBAL_THREADS_ONLY */

#ifndef _PR_LOCAL_THREADS_ONLY
	if (_native_threads_only) {
		is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
		if (is == 0) {
			lock->owner = me;
			return PR_TRUE;
		}
    	return PR_FALSE;
	}
#endif

    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSOFF(is);

    _PR_LOCK_LOCK(lock);
    if (lock->owner == 0) {
        /* Just got the lock */
        lock->owner = me;
        lock->priority = me->priority;
		/* Add the granted lock to this owning thread's lock list */
        PR_APPEND_LINK(&lock->links, &me->lockList);
        rv = PR_TRUE;
    }
    _PR_LOCK_UNLOCK(lock);

    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSON(is);
    return rv;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

/************************************************************************/
/************************************************************************/
/***********************ROUTINES FOR DCE EMULATION***********************/
/************************************************************************/
/************************************************************************/
PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
    { return (PR_TestAndLock(lock)) ? PR_SUCCESS : PR_FAILURE; }

deps/mozilla/nsprpub/pr/src/threads/combined/prustack.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

/* List of free stack virtual memory chunks */
PRLock *_pr_stackLock;
PRCList _pr_freeStacks = PR_INIT_STATIC_CLIST(&_pr_freeStacks);
PRIntn _pr_numFreeStacks;
PRIntn _pr_maxFreeStacks = 4;

#ifdef DEBUG
/*
** A variable that can be set via the debugger...
*/
PRBool _pr_debugStacks = PR_FALSE;
#endif

/* How much space to leave between the stacks, at each end */
#define REDZONE		(2 << _pr_pageShift)

#define _PR_THREAD_STACK_PTR(_qp) \
    ((PRThreadStack*) ((char*) (_qp) - offsetof(PRThreadStack,links)))

void _PR_InitStacks(void)
{
    _pr_stackLock = PR_NewLock();
}

void _PR_CleanupStacks(void)
{
    if (_pr_stackLock) {
        PR_DestroyLock(_pr_stackLock);
        _pr_stackLock = NULL;
    }
}

/*
** Allocate a stack for a thread.
*/
PRThreadStack *_PR_NewStack(PRUint32 stackSize)
{
    PRCList *qp;
    PRThreadStack *ts;
    PRThread *thr;

    /*
    ** Trim the list of free stacks. Trim it backwards, tossing out the
    ** oldest stack found first (this way more recent stacks have a
    ** chance of being present in the data cache).
    */
    PR_Lock(_pr_stackLock);
    qp = _pr_freeStacks.prev;
    while ((_pr_numFreeStacks > _pr_maxFreeStacks) && (qp != &_pr_freeStacks)) {
	ts = _PR_THREAD_STACK_PTR(qp);
	thr = _PR_THREAD_STACK_TO_PTR(ts);
	qp = qp->prev;
	/*
	 * skip stacks which are still being used
	 */
	if (thr->no_sched)
		continue;
	PR_REMOVE_LINK(&ts->links);

	/* Give platform OS to clear out the stack for debugging */
	_PR_MD_CLEAR_STACK(ts);

	_pr_numFreeStacks--;
	_PR_DestroySegment(ts->seg);
	PR_DELETE(ts);
    }

    /*
    ** Find a free thread stack. This searches the list of free'd up
    ** virtually mapped thread stacks.
    */
    qp = _pr_freeStacks.next;
    ts = 0;
    while (qp != &_pr_freeStacks) {
	ts = _PR_THREAD_STACK_PTR(qp);
	thr = _PR_THREAD_STACK_TO_PTR(ts);
	qp = qp->next;
	/*
	 * skip stacks which are still being used
	 */
	if ((!(thr->no_sched)) && ((ts->allocSize - 2*REDZONE) >= stackSize)) {
	    /*
	    ** Found a stack that is not in use and is big enough. Change
	    ** stackSize to fit it.
	    */
	    stackSize = ts->allocSize - 2*REDZONE;
	    PR_REMOVE_LINK(&ts->links);
	    _pr_numFreeStacks--;
	    ts->links.next = 0;
	    ts->links.prev = 0;
	    PR_Unlock(_pr_stackLock);
	    goto done;
	}
	ts = 0;
    }
    PR_Unlock(_pr_stackLock);

    if (!ts) {
	/* Make a new thread stack object. */
	ts = PR_NEWZAP(PRThreadStack);
	if (!ts) {
	    return NULL;
	}

	/*
	** Assign some of the virtual space to the new stack object. We
	** may not get that piece of VM, but if nothing else we will
	** advance the pointer so we don't collide (unless the OS screws
	** up).
	*/
	ts->allocSize = stackSize + 2*REDZONE;
	ts->seg = _PR_NewSegment(ts->allocSize, 0);
	if (!ts->seg) {
	    PR_DELETE(ts);
	    return NULL;
	}
	}

  done:
    ts->allocBase = (char*)ts->seg->vaddr;
    ts->flags = _PR_STACK_MAPPED;
    ts->stackSize = stackSize;

#ifdef HAVE_STACK_GROWING_UP
    ts->stackTop = ts->allocBase + REDZONE;
    ts->stackBottom = ts->stackTop + stackSize;
#else
    ts->stackBottom = ts->allocBase + REDZONE;
    ts->stackTop = ts->stackBottom + stackSize;
#endif

    PR_LOG(_pr_thread_lm, PR_LOG_NOTICE,
	   ("thread stack: base=0x%x limit=0x%x bottom=0x%x top=0x%x\n",
	    ts->allocBase, ts->allocBase + ts->allocSize - 1,
	    ts->allocBase + REDZONE,
	    ts->allocBase + REDZONE + stackSize - 1));
	    
    _PR_MD_INIT_STACK(ts,REDZONE);

    return ts;
}

/*
** Free the stack for the current thread
*/
void _PR_FreeStack(PRThreadStack *ts)
{
    if (!ts) {
	return;
    }
    if (ts->flags & _PR_STACK_PRIMORDIAL) {
	PR_DELETE(ts);
	return;
    }

    /*
    ** Put the stack on the free list. This is done because we are still
    ** using the stack. Next time a thread is created we will trim the
    ** list down; it's safe to do it then because we will have had to
    ** context switch to a live stack before another thread can be
    ** created.
    */
    PR_Lock(_pr_stackLock);
    PR_APPEND_LINK(&ts->links, _pr_freeStacks.prev);
    _pr_numFreeStacks++;
    PR_Unlock(_pr_stackLock);
}

deps/mozilla/nsprpub/pr/src/threads/combined/pruthr.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"
#include <signal.h>
#include <string.h>

#if defined(WIN95)                                                                         
/*
** Some local variables report warnings on Win95 because the code paths
** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
** The pragma suppresses the warning.
**
*/
#pragma warning(disable : 4101)
#endif          

/* _pr_activeLock protects the following global variables */
PRLock *_pr_activeLock;
PRInt32 _pr_primordialExitCount;   /* In PR_Cleanup(), the primordial thread
                    * waits until all other user (non-system)
                    * threads have terminated before it exits.
                    * So whenever we decrement _pr_userActive,
                    * it is compared with
                    * _pr_primordialExitCount.
                    * If the primordial thread is a system
                    * thread, then _pr_primordialExitCount
                    * is 0.  If the primordial thread is
                    * itself a user thread, then 
                    * _pr_primordialThread is 1.
                    */
PRCondVar *_pr_primordialExitCVar; /* When _pr_userActive is decremented to
                    * _pr_primordialExitCount, this condition
                    * variable is notified.
                    */

PRLock *_pr_deadQLock;
PRUint32 _pr_numNativeDead;
PRUint32 _pr_numUserDead;
PRCList _pr_deadNativeQ;
PRCList _pr_deadUserQ;

PRUint32 _pr_join_counter;

PRUint32 _pr_local_threads;
PRUint32 _pr_global_threads;

PRBool suspendAllOn = PR_FALSE;
PRThread *suspendAllThread = NULL;

extern PRCList _pr_active_global_threadQ;
extern PRCList _pr_active_local_threadQ;

static void _PR_DecrActiveThreadCount(PRThread *thread);
static PRThread *_PR_AttachThread(PRThreadType, PRThreadPriority, PRThreadStack *);
static void _PR_InitializeNativeStack(PRThreadStack *ts);
static void _PR_InitializeRecycledThread(PRThread *thread);
static void _PR_UserRunThread(void);

void _PR_InitThreads(PRThreadType type, PRThreadPriority priority,
    PRUintn maxPTDs)
{
    PRThread *thread;
    PRThreadStack *stack;

    _pr_terminationCVLock = PR_NewLock();
    _pr_activeLock = PR_NewLock();

#ifndef HAVE_CUSTOM_USER_THREADS
    stack = PR_NEWZAP(PRThreadStack);
#ifdef HAVE_STACK_GROWING_UP
    stack->stackTop = (char*) ((((long)&type) >> _pr_pageShift)
                  << _pr_pageShift);
#else
#if defined(SOLARIS) || defined (UNIXWARE) && defined (USR_SVR4_THREADS)
    stack->stackTop = (char*) &thread;
#else
    stack->stackTop = (char*) ((((long)&type + _pr_pageSize - 1)
                >> _pr_pageShift) << _pr_pageShift);
#endif
#endif
#else
    /* If stack is NULL, we're using custom user threads like NT fibers. */
    stack = PR_NEWZAP(PRThreadStack);
    if (stack) {
        stack->stackSize = 0;
        _PR_InitializeNativeStack(stack);
    }
#endif /* HAVE_CUSTOM_USER_THREADS */

    thread = _PR_AttachThread(type, priority, stack);
    if (thread) {
        _PR_MD_SET_CURRENT_THREAD(thread);

        if (type == PR_SYSTEM_THREAD) {
            thread->flags = _PR_SYSTEM;
            _pr_systemActive++;
            _pr_primordialExitCount = 0;
        } else {
            _pr_userActive++;
            _pr_primordialExitCount = 1;
        }
    thread->no_sched = 1;
    _pr_primordialExitCVar = PR_NewCondVar(_pr_activeLock);
    }

    if (!thread) PR_Abort();
#ifdef _PR_LOCAL_THREADS_ONLY
    thread->flags |= _PR_PRIMORDIAL;
#else
    thread->flags |= _PR_PRIMORDIAL | _PR_GLOBAL_SCOPE;
#endif

    /*
     * Needs _PR_PRIMORDIAL flag set before calling
     * _PR_MD_INIT_THREAD()
     */
    if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
        /*
         * XXX do what?
         */
    }

    if (_PR_IS_NATIVE_THREAD(thread)) {
        PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
        _pr_global_threads++;
    } else {
        PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
        _pr_local_threads++;
    }

    _pr_recycleThreads = 0;
    _pr_deadQLock = PR_NewLock();
    _pr_numNativeDead = 0;
    _pr_numUserDead = 0;
    PR_INIT_CLIST(&_pr_deadNativeQ);
    PR_INIT_CLIST(&_pr_deadUserQ);
}

void _PR_CleanupThreads(void)
{
    if (_pr_terminationCVLock) {
        PR_DestroyLock(_pr_terminationCVLock);
        _pr_terminationCVLock = NULL;
    }
    if (_pr_activeLock) {
        PR_DestroyLock(_pr_activeLock);
        _pr_activeLock = NULL;
    }
    if (_pr_primordialExitCVar) {
        PR_DestroyCondVar(_pr_primordialExitCVar);
        _pr_primordialExitCVar = NULL;
    }
    /* TODO _pr_dead{Native,User}Q need to be deleted */
    if (_pr_deadQLock) {
        PR_DestroyLock(_pr_deadQLock);
        _pr_deadQLock = NULL;
    }
}

/*
** Initialize a stack for a native thread
*/
static void _PR_InitializeNativeStack(PRThreadStack *ts)
{
    if( ts && (ts->stackTop == 0) ) {
        ts->allocSize = ts->stackSize;

        /*
        ** Setup stackTop and stackBottom values.
        */
#ifdef HAVE_STACK_GROWING_UP
    ts->allocBase = (char*) ((((long)&ts) >> _pr_pageShift)
                  << _pr_pageShift);
        ts->stackBottom = ts->allocBase + ts->stackSize;
        ts->stackTop = ts->allocBase;
#else
        ts->allocBase = (char*) ((((long)&ts + _pr_pageSize - 1)
                >> _pr_pageShift) << _pr_pageShift);
        ts->stackTop    = ts->allocBase;
        ts->stackBottom = ts->allocBase - ts->stackSize;
#endif
    }
}

void _PR_NotifyJoinWaiters(PRThread *thread)
{
    /*
    ** Handle joinable threads.  Change the state to waiting for join.
    ** Remove from our run Q and put it on global waiting to join Q.
    ** Notify on our "termination" condition variable so that joining
    ** thread will know about our termination.  Switch our context and
    ** come back later on to continue the cleanup.
    */    
    PR_ASSERT(thread == _PR_MD_CURRENT_THREAD());
    if (thread->term != NULL) {
        PR_Lock(_pr_terminationCVLock);
        _PR_THREAD_LOCK(thread);
        thread->state = _PR_JOIN_WAIT;
        if ( !_PR_IS_NATIVE_THREAD(thread) ) {
            _PR_MISCQ_LOCK(thread->cpu);
            _PR_ADD_JOINQ(thread, thread->cpu);
            _PR_MISCQ_UNLOCK(thread->cpu);
        }
        _PR_THREAD_UNLOCK(thread);
        PR_NotifyCondVar(thread->term);
        PR_Unlock(_pr_terminationCVLock);
        _PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT);
        PR_ASSERT(thread->state != _PR_JOIN_WAIT);
    }

}

/*
 * Zero some of the data members of a recycled thread.
 *
 * Note that we can do this either when a dead thread is added to
 * the dead thread queue or when it is reused.  Here, we are doing
 * this lazily, when the thread is reused in _PR_CreateThread().
 */
static void _PR_InitializeRecycledThread(PRThread *thread)
{
    /*
     * Assert that the following data members are already zeroed
     * by _PR_CleanupThread().
     */
#ifdef DEBUG
    if (thread->privateData) {
        unsigned int i;
        for (i = 0; i < thread->tpdLength; i++) {
            PR_ASSERT(thread->privateData[i] == NULL);
        }
    }
#endif
    PR_ASSERT(thread->dumpArg == 0 && thread->dump == 0);
    PR_ASSERT(thread->errorString == 0 && thread->errorStringSize == 0);
    PR_ASSERT(thread->errorStringLength == 0);

    /* Reset data members in thread structure */
    thread->errorCode = thread->osErrorCode = 0;
    thread->io_pending = thread->io_suspended = PR_FALSE;
    thread->environment = 0;
    PR_INIT_CLIST(&thread->lockList);
}

PRStatus _PR_RecycleThread(PRThread *thread)
{
    if ( _PR_IS_NATIVE_THREAD(thread) &&
            _PR_NUM_DEADNATIVE < _pr_recycleThreads) {
        _PR_DEADQ_LOCK;
        PR_APPEND_LINK(&thread->links, &_PR_DEADNATIVEQ);
        _PR_INC_DEADNATIVE;
        _PR_DEADQ_UNLOCK;
    return (PR_SUCCESS);
    } else if ( !_PR_IS_NATIVE_THREAD(thread) &&
                _PR_NUM_DEADUSER < _pr_recycleThreads) {
        _PR_DEADQ_LOCK;
        PR_APPEND_LINK(&thread->links, &_PR_DEADUSERQ);
        _PR_INC_DEADUSER;
        _PR_DEADQ_UNLOCK;
    return (PR_SUCCESS);
    }
    return (PR_FAILURE);
}

/*
 * Decrement the active thread count, either _pr_systemActive or
 * _pr_userActive, depending on whether the thread is a system thread
 * or a user thread.  If all the user threads, except possibly
 * the primordial thread, have terminated, we notify the primordial
 * thread of this condition.
 *
 * Since this function will lock _pr_activeLock, do not call this
 * function while holding the _pr_activeLock lock, as this will result
 * in a deadlock.
 */

static void
_PR_DecrActiveThreadCount(PRThread *thread)
{
    PR_Lock(_pr_activeLock);
    if (thread->flags & _PR_SYSTEM) {
        _pr_systemActive--;
    } else {
        _pr_userActive--;
        if (_pr_userActive == _pr_primordialExitCount) {
            PR_NotifyCondVar(_pr_primordialExitCVar);
        }
    }
    PR_Unlock(_pr_activeLock);
}

/*
** Detach thread structure
*/
static void
_PR_DestroyThread(PRThread *thread)
{
    _PR_MD_FREE_LOCK(&thread->threadLock);
    PR_DELETE(thread);
}

void
_PR_NativeDestroyThread(PRThread *thread)
{
    if(thread->term) {
        PR_DestroyCondVar(thread->term);
        thread->term = 0;
    }
    if (NULL != thread->privateData) {
        PR_ASSERT(0 != thread->tpdLength);
        PR_DELETE(thread->privateData);
        thread->tpdLength = 0;
    }
    PR_DELETE(thread->stack);
    _PR_DestroyThread(thread);
}

void
_PR_UserDestroyThread(PRThread *thread)
{
    if(thread->term) {
        PR_DestroyCondVar(thread->term);
        thread->term = 0;
    }
    if (NULL != thread->privateData) {
        PR_ASSERT(0 != thread->tpdLength);
        PR_DELETE(thread->privateData);
        thread->tpdLength = 0;
    }
    _PR_MD_FREE_LOCK(&thread->threadLock);
    if (thread->threadAllocatedOnStack == 1) {
        _PR_MD_CLEAN_THREAD(thread);
        /*
         *  Because the no_sched field is set, this thread/stack will
         *  will not be re-used until the flag is cleared by the thread
         *  we will context switch to.
         */
        _PR_FreeStack(thread->stack);
    } else {
#ifdef WINNT
        _PR_MD_CLEAN_THREAD(thread);
#else
        /*
         * This assertion does not apply to NT.  On NT, every fiber
         * has its threadAllocatedOnStack equal to 0.  Elsewhere,
         * only the primordial thread has its threadAllocatedOnStack
         * equal to 0.
         */
        PR_ASSERT(thread->flags & _PR_PRIMORDIAL);
#endif
    }
}


/*
** Run a thread's start function. When the start function returns the
** thread is done executing and no longer needs the CPU. If there are no
** more user threads running then we can exit the program.
*/
void _PR_NativeRunThread(void *arg)
{
    PRThread *thread = (PRThread *)arg;

    _PR_MD_SET_CURRENT_THREAD(thread);

    _PR_MD_SET_CURRENT_CPU(NULL);

    /* Set up the thread stack information */
    _PR_InitializeNativeStack(thread->stack);

    /* Set up the thread md information */
    if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
        /*
         * thread failed to initialize itself, possibly due to
         * failure to allocate per-thread resources
         */
        return;
    }

    while(1) {
        thread->state = _PR_RUNNING;

        /*
         * Add to list of active threads
         */
        PR_Lock(_pr_activeLock);
        PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
        _pr_global_threads++;
        PR_Unlock(_pr_activeLock);

        (*thread->startFunc)(thread->arg);

        /*
         * The following two assertions are meant for NT asynch io.
         *
         * The thread should have no asynch io in progress when it
         * exits, otherwise the overlapped buffer, which is part of
         * the thread structure, would become invalid.
         */
        PR_ASSERT(thread->io_pending == PR_FALSE);
        /*
         * This assertion enforces the programming guideline that
         * if an io function times out or is interrupted, the thread
         * should close the fd to force the asynch io to abort
         * before it exits.  Right now, closing the fd is the only
         * way to clear the io_suspended flag.
         */
        PR_ASSERT(thread->io_suspended == PR_FALSE);

        /*
         * remove thread from list of active threads
         */
        PR_Lock(_pr_activeLock);
        PR_REMOVE_LINK(&thread->active);
        _pr_global_threads--;
        PR_Unlock(_pr_activeLock);

        PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));

        /* All done, time to go away */
        _PR_CleanupThread(thread);

        _PR_NotifyJoinWaiters(thread);

        _PR_DecrActiveThreadCount(thread);

        thread->state = _PR_DEAD_STATE;

        if (!_pr_recycleThreads || (_PR_RecycleThread(thread) ==
                        PR_FAILURE)) {
            /*
             * thread not recycled
             * platform-specific thread exit processing
             *        - for stuff like releasing native-thread resources, etc.
             */
            _PR_MD_EXIT_THREAD(thread);
            /*
             * Free memory allocated for the thread
             */
            _PR_NativeDestroyThread(thread);
            /*
             * thread gone, cannot de-reference thread now
             */
            return;
        }

        /* Now wait for someone to activate us again... */
        _PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT);
    }
}

static void _PR_UserRunThread(void)
{
    PRThread *thread = _PR_MD_CURRENT_THREAD();
    PRIntn is;

    if (_MD_LAST_THREAD())
    _MD_LAST_THREAD()->no_sched = 0;

#ifdef HAVE_CUSTOM_USER_THREADS
    if (thread->stack == NULL) {
        thread->stack = PR_NEWZAP(PRThreadStack);
        _PR_InitializeNativeStack(thread->stack);
    }
#endif /* HAVE_CUSTOM_USER_THREADS */

    while(1) {
        /* Run thread main */
        if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_MD_SET_INTSOFF(0);

    /*
     * Add to list of active threads
     */
    if (!(thread->flags & _PR_IDLE_THREAD)) {
        PR_Lock(_pr_activeLock);
        PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
        _pr_local_threads++;
        PR_Unlock(_pr_activeLock);
    }

        (*thread->startFunc)(thread->arg);

        /*
         * The following two assertions are meant for NT asynch io.
         *
         * The thread should have no asynch io in progress when it
         * exits, otherwise the overlapped buffer, which is part of
         * the thread structure, would become invalid.
         */
        PR_ASSERT(thread->io_pending == PR_FALSE);
        /*
         * This assertion enforces the programming guideline that
         * if an io function times out or is interrupted, the thread
         * should close the fd to force the asynch io to abort
         * before it exits.  Right now, closing the fd is the only
         * way to clear the io_suspended flag.
         */
        PR_ASSERT(thread->io_suspended == PR_FALSE);

        PR_Lock(_pr_activeLock);
    /*
     * remove thread from list of active threads
     */
    if (!(thread->flags & _PR_IDLE_THREAD)) {
           PR_REMOVE_LINK(&thread->active);
        _pr_local_threads--;
    }
    PR_Unlock(_pr_activeLock);
        PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));

        /* All done, time to go away */
        _PR_CleanupThread(thread);

        _PR_INTSOFF(is);    

        _PR_NotifyJoinWaiters(thread);

    _PR_DecrActiveThreadCount(thread);

        thread->state = _PR_DEAD_STATE;

        if (!_pr_recycleThreads || (_PR_RecycleThread(thread) ==
                        PR_FAILURE)) {
            /*
            ** Destroy the thread resources
            */
        _PR_UserDestroyThread(thread);
        }

        /*
        ** Find another user thread to run. This cpu has finished the
        ** previous threads main and is now ready to run another thread.
        */
        {
            PRInt32 is;
            _PR_INTSOFF(is);
            _PR_MD_SWITCH_CONTEXT(thread);
        }

        /* Will land here when we get scheduled again if we are recycling... */
    }
}

void _PR_SetThreadPriority(PRThread *thread, PRThreadPriority newPri)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRIntn is;

    if ( _PR_IS_NATIVE_THREAD(thread) ) {
        _PR_MD_SET_PRIORITY(&(thread->md), newPri);
        return;
    }

    if (!_PR_IS_NATIVE_THREAD(me))
    _PR_INTSOFF(is);
    _PR_THREAD_LOCK(thread);
    if (newPri != thread->priority) {
    _PRCPU *cpu = thread->cpu;

    switch (thread->state) {
      case _PR_RUNNING:
        /* Change my priority */

            _PR_RUNQ_LOCK(cpu);
        thread->priority = newPri;
        if (_PR_RUNQREADYMASK(cpu) >> (newPri + 1)) {
            if (!_PR_IS_NATIVE_THREAD(me))
                    _PR_SET_RESCHED_FLAG();
        }
            _PR_RUNQ_UNLOCK(cpu);
        break;

      case _PR_RUNNABLE:

        _PR_RUNQ_LOCK(cpu);
            /* Move to different runQ */
            _PR_DEL_RUNQ(thread);
            thread->priority = newPri;
            PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
            _PR_ADD_RUNQ(thread, cpu, newPri);
        _PR_RUNQ_UNLOCK(cpu);

            if (newPri > me->priority) {
            if (!_PR_IS_NATIVE_THREAD(me))
                    _PR_SET_RESCHED_FLAG();
            }

        break;

      case _PR_LOCK_WAIT:
      case _PR_COND_WAIT:
      case _PR_IO_WAIT:
      case _PR_SUSPENDED:

        thread->priority = newPri;
        break;
    }
    }
    _PR_THREAD_UNLOCK(thread);
    if (!_PR_IS_NATIVE_THREAD(me))
    _PR_INTSON(is);
}

/*
** Suspend the named thread and copy its gc registers into regBuf
*/
static void _PR_Suspend(PRThread *thread)
{
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT(thread != me);
    PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread) || (!thread->cpu));

    if (!_PR_IS_NATIVE_THREAD(me))
        _PR_INTSOFF(is);
    _PR_THREAD_LOCK(thread);
    switch (thread->state) {
      case _PR_RUNNABLE:
        if (!_PR_IS_NATIVE_THREAD(thread)) {
            _PR_RUNQ_LOCK(thread->cpu);
            _PR_DEL_RUNQ(thread);
            _PR_RUNQ_UNLOCK(thread->cpu);

            _PR_MISCQ_LOCK(thread->cpu);
            _PR_ADD_SUSPENDQ(thread, thread->cpu);
            _PR_MISCQ_UNLOCK(thread->cpu);
        } else {
            /*
             * Only LOCAL threads are suspended by _PR_Suspend
             */
             PR_ASSERT(0);
        }
        thread->state = _PR_SUSPENDED;
        break;

      case _PR_RUNNING:
        /*
         * The thread being suspended should be a LOCAL thread with
         * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
         */
        PR_ASSERT(0);
        break;

      case _PR_LOCK_WAIT:
      case _PR_IO_WAIT:
      case _PR_COND_WAIT:
        if (_PR_IS_NATIVE_THREAD(thread)) {
            _PR_MD_SUSPEND_THREAD(thread);
    }
        thread->flags |= _PR_SUSPENDING;
        break;

      default:
        PR_Abort();
    }
    _PR_THREAD_UNLOCK(thread);
    if (!_PR_IS_NATIVE_THREAD(me))
    _PR_INTSON(is);
}

static void _PR_Resume(PRThread *thread)
{
    PRThreadPriority pri;
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if (!_PR_IS_NATIVE_THREAD(me))
    _PR_INTSOFF(is);
    _PR_THREAD_LOCK(thread);
    switch (thread->state) {
      case _PR_SUSPENDED:
        thread->state = _PR_RUNNABLE;
        thread->flags &= ~_PR_SUSPENDING;
        if (!_PR_IS_NATIVE_THREAD(thread)) {
            _PR_MISCQ_LOCK(thread->cpu);
            _PR_DEL_SUSPENDQ(thread);
            _PR_MISCQ_UNLOCK(thread->cpu);

            pri = thread->priority;

            _PR_RUNQ_LOCK(thread->cpu);
            _PR_ADD_RUNQ(thread, thread->cpu, pri);
            _PR_RUNQ_UNLOCK(thread->cpu);

            if (pri > _PR_MD_CURRENT_THREAD()->priority) {
                if (!_PR_IS_NATIVE_THREAD(me))
                    _PR_SET_RESCHED_FLAG();
            }
        } else {
            PR_ASSERT(0);
        }
        break;

      case _PR_IO_WAIT:
      case _PR_COND_WAIT:
        thread->flags &= ~_PR_SUSPENDING;
/*      PR_ASSERT(thread->wait.monitor->stickyCount == 0); */
        break;

      case _PR_LOCK_WAIT: 
      {
        PRLock *wLock = thread->wait.lock;

        thread->flags &= ~_PR_SUSPENDING;
 
        _PR_LOCK_LOCK(wLock);
        if (thread->wait.lock->owner == 0) {
            _PR_UnblockLockWaiter(thread->wait.lock);
        }
        _PR_LOCK_UNLOCK(wLock);
        break;
      }
      case _PR_RUNNABLE:
        break;
      case _PR_RUNNING:
        /*
         * The thread being suspended should be a LOCAL thread with
         * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
         */
        PR_ASSERT(0);
        break;

      default:
    /*
     * thread should have been in one of the above-listed blocked states
     * (_PR_JOIN_WAIT, _PR_IO_WAIT, _PR_UNBORN, _PR_DEAD_STATE)
     */
        PR_Abort();
    }
    _PR_THREAD_UNLOCK(thread);
    if (!_PR_IS_NATIVE_THREAD(me))
        _PR_INTSON(is);

}

#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus)
{
    PRThread *thread;
    PRIntn pri;
    PRUint32 r;
    PRCList *qp;
    PRIntn priMin, priMax;

    _PR_RUNQ_LOCK(cpu);
    r = _PR_RUNQREADYMASK(cpu);
    if (r==0) {
        priMin = priMax = PR_PRIORITY_FIRST;
    } else if (r == (1<<PR_PRIORITY_NORMAL) ) {
        priMin = priMax = PR_PRIORITY_NORMAL;
    } else {
        priMin = PR_PRIORITY_FIRST;
        priMax = PR_PRIORITY_LAST;
    }
    thread = NULL;
    for (pri = priMax; pri >= priMin ; pri-- ) {
    if (r & (1 << pri)) {
            for (qp = _PR_RUNQ(cpu)[pri].next; 
                 qp != &_PR_RUNQ(cpu)[pri];
                 qp = qp->next) {
                thread = _PR_THREAD_PTR(qp);
                /*
                * skip non-schedulable threads
                */
                PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
                if (thread->no_sched) {
                    thread = NULL;
                    /*
                     * Need to wakeup cpus to avoid missing a
                     * runnable thread
                     * Waking up all CPU's need happen only once.
                     */

                    *wakeup_cpus = PR_TRUE;
                    continue;
                } else if (thread->flags & _PR_BOUND_THREAD) {
                    /*
                     * Thread bound to cpu 0
                     */

                    thread = NULL;
#ifdef IRIX
					_PR_MD_WAKEUP_PRIMORDIAL_CPU();
#endif
                    continue;
                } else if (thread->io_pending == PR_TRUE) {
                    /*
                     * A thread that is blocked for I/O needs to run
                     * on the same cpu on which it was blocked. This is because
                     * the cpu's ioq is accessed without lock protection and scheduling
                     * the thread on a different cpu would preclude this optimization.
                     */
                    thread = NULL;
                    continue;
                } else {
                    /* Pull thread off of its run queue */
                    _PR_DEL_RUNQ(thread);
                    _PR_RUNQ_UNLOCK(cpu);
                    return(thread);
                }
            }
        }
        thread = NULL;
    }
    _PR_RUNQ_UNLOCK(cpu);
    return(thread);
}
#endif /* !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX) */

/*
** Schedule this native thread by finding the highest priority nspr
** thread that is ready to run.
**
** Note- everyone really needs to call _PR_MD_SWITCH_CONTEXT (which calls
**       PR_Schedule() rather than calling PR_Schedule.  Otherwise if there
**       is initialization required for switching from SWITCH_CONTEXT,
**       it will not get done!
*/
void _PR_Schedule(void)
{
    PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
    _PRCPU *cpu = _PR_MD_CURRENT_CPU();
    PRIntn pri;
    PRUint32 r;
    PRCList *qp;
    PRIntn priMin, priMax;
#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
    PRBool wakeup_cpus;
#endif

    /* Interrupts must be disabled */
    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);

    /* Since we are rescheduling, we no longer want to */
    _PR_CLEAR_RESCHED_FLAG();

    /*
    ** Find highest priority thread to run. Bigger priority numbers are
    ** higher priority threads
    */
    _PR_RUNQ_LOCK(cpu);
    /*
     *  if we are in SuspendAll mode, can schedule only the thread
     *    that called PR_SuspendAll
     *
     *  The thread may be ready to run now, after completing an I/O
     *  operation, for example
     */
    if ((thread = suspendAllThread) != 0) {
    if ((!(thread->no_sched)) && (thread->state == _PR_RUNNABLE)) {
            /* Pull thread off of its run queue */
            _PR_DEL_RUNQ(thread);
            _PR_RUNQ_UNLOCK(cpu);
            goto found_thread;
    } else {
            thread = NULL;
            _PR_RUNQ_UNLOCK(cpu);
            goto idle_thread;
    }
    }
    r = _PR_RUNQREADYMASK(cpu);
    if (r==0) {
        priMin = priMax = PR_PRIORITY_FIRST;
    } else if (r == (1<<PR_PRIORITY_NORMAL) ) {
        priMin = priMax = PR_PRIORITY_NORMAL;
    } else {
        priMin = PR_PRIORITY_FIRST;
        priMax = PR_PRIORITY_LAST;
    }
    thread = NULL;
    for (pri = priMax; pri >= priMin ; pri-- ) {
    if (r & (1 << pri)) {
            for (qp = _PR_RUNQ(cpu)[pri].next; 
                 qp != &_PR_RUNQ(cpu)[pri];
                 qp = qp->next) {
                thread = _PR_THREAD_PTR(qp);
                /*
                * skip non-schedulable threads
                */
                PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
                if ((thread->no_sched) && (me != thread)){
                    thread = NULL;
                    continue;
                } else {
                    /* Pull thread off of its run queue */
                    _PR_DEL_RUNQ(thread);
                    _PR_RUNQ_UNLOCK(cpu);
                    goto found_thread;
                }
            }
        }
        thread = NULL;
    }
    _PR_RUNQ_UNLOCK(cpu);

#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)

    wakeup_cpus = PR_FALSE;
    _PR_CPU_LIST_LOCK();
    for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {
        if (cpu != _PR_CPU_PTR(qp)) {
            if ((thread = get_thread(_PR_CPU_PTR(qp), &wakeup_cpus))
                                        != NULL) {
                thread->cpu = cpu;
                _PR_CPU_LIST_UNLOCK();
                if (wakeup_cpus == PR_TRUE)
                    _PR_MD_WAKEUP_CPUS();
                goto found_thread;
            }
        }
    }
    _PR_CPU_LIST_UNLOCK();
    if (wakeup_cpus == PR_TRUE)
        _PR_MD_WAKEUP_CPUS();

#endif        /* _PR_LOCAL_THREADS_ONLY */

idle_thread:
   /*
    ** There are no threads to run. Switch to the idle thread
    */
    PR_LOG(_pr_sched_lm, PR_LOG_MAX, ("pausing"));
    thread = _PR_MD_CURRENT_CPU()->idle_thread;

found_thread:
    PR_ASSERT((me == thread) || ((thread->state == _PR_RUNNABLE) &&
                    (!(thread->no_sched))));

    /* Resume the thread */
    PR_LOG(_pr_sched_lm, PR_LOG_MAX,
       ("switching to %d[%p]", thread->id, thread));
    PR_ASSERT(thread->state != _PR_RUNNING);
    thread->state = _PR_RUNNING;
 
    /* If we are on the runq, it just means that we went to sleep on some
     * resource, and by the time we got here another real native thread had
     * already given us the resource and put us back on the runqueue 
     */
	PR_ASSERT(thread->cpu == _PR_MD_CURRENT_CPU());
    if (thread != me) 
        _PR_MD_RESTORE_CONTEXT(thread);
#if 0
    /* XXXMB; with setjmp/longjmp it is impossible to land here, but 
     * it is not with fibers... Is this a bad thing?  I believe it is 
     * still safe.
     */
    PR_NOT_REACHED("impossible return from schedule");
#endif
}

/*
** Attaches a thread.  
** Does not set the _PR_MD_CURRENT_THREAD.  
** Does not specify the scope of the thread.
*/
static PRThread *
_PR_AttachThread(PRThreadType type, PRThreadPriority priority,
    PRThreadStack *stack)
{
    PRThread *thread;
    char *mem;

    if (priority > PR_PRIORITY_LAST) {
        priority = PR_PRIORITY_LAST;
    } else if (priority < PR_PRIORITY_FIRST) {
        priority = PR_PRIORITY_FIRST;
    }

    mem = (char*) PR_CALLOC(sizeof(PRThread));
    if (mem) {
        thread = (PRThread*) mem;
        thread->priority = priority;
        thread->stack = stack;
        thread->state = _PR_RUNNING;
        PR_INIT_CLIST(&thread->lockList);
        if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {
        PR_DELETE(thread);
        return 0;
    }

        return thread;
    }
    return 0;
}



PR_IMPLEMENT(PRThread*) 
_PR_NativeCreateThread(PRThreadType type,
                     void (*start)(void *arg),
                     void *arg,
                     PRThreadPriority priority,
                     PRThreadScope scope,
                     PRThreadState state,
                     PRUint32 stackSize,
                     PRUint32 flags)
{
    PRThread *thread;

    thread = _PR_AttachThread(type, priority, NULL);

    if (thread) {
        PR_Lock(_pr_activeLock);
        thread->flags = (flags | _PR_GLOBAL_SCOPE);
        thread->id = ++_pr_utid;
        if (type == PR_SYSTEM_THREAD) {
            thread->flags |= _PR_SYSTEM;
            _pr_systemActive++;
        } else {
            _pr_userActive++;
        }
        PR_Unlock(_pr_activeLock);

        thread->stack = PR_NEWZAP(PRThreadStack);
        if (!thread->stack) {
            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
            goto done;
        }
        thread->stack->stackSize = stackSize?stackSize:_MD_DEFAULT_STACK_SIZE;
        thread->stack->thr = thread;
        thread->startFunc = start;
        thread->arg = arg;

        /* 
          Set thread flags related to scope and joinable state. If joinable
          thread, allocate a "termination" conidition variable.
         */
        if (state == PR_JOINABLE_THREAD) {
            thread->term = PR_NewCondVar(_pr_terminationCVLock);
        if (thread->term == NULL) {
        PR_DELETE(thread->stack);
        goto done;
        }
        }

    thread->state = _PR_RUNNING;
        if (_PR_MD_CREATE_THREAD(thread, _PR_NativeRunThread, priority,
            scope,state,stackSize) == PR_SUCCESS) {
            return thread;
        }
        if (thread->term) {
            PR_DestroyCondVar(thread->term);
            thread->term = NULL;
        }
    PR_DELETE(thread->stack);
    }

done:
    if (thread) {
    _PR_DecrActiveThreadCount(thread);
        _PR_DestroyThread(thread);
    }
    return NULL;
}

/************************************************************************/

PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
                     void (*start)(void *arg),
                     void *arg,
                     PRThreadPriority priority,
                     PRThreadScope scope,
                     PRThreadState state,
                     PRUint32 stackSize,
                     PRUint32 flags)
{
    PRThread *me;
    PRThread *thread = NULL;
    PRThreadStack *stack;
    char *top;
    PRIntn is;
    PRIntn native = 0;
    PRIntn useRecycled = 0;
    PRBool status;

    /* 
    First, pin down the priority.  Not all compilers catch passing out of
    range enum here.  If we let bad values thru, priority queues won't work.
    */
    if (priority > PR_PRIORITY_LAST) {
        priority = PR_PRIORITY_LAST;
    } else if (priority < PR_PRIORITY_FIRST) {
        priority = PR_PRIORITY_FIRST;
    }
        
    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (! (flags & _PR_IDLE_THREAD))
        me = _PR_MD_CURRENT_THREAD();

#if    defined(_PR_GLOBAL_THREADS_ONLY)
	/*
	 * can create global threads only
	 */
    if (scope == PR_LOCAL_THREAD)
    	scope = PR_GLOBAL_THREAD;
#endif

	if (_native_threads_only)
		scope = PR_GLOBAL_THREAD;

    native = (((scope == PR_GLOBAL_THREAD)|| (scope == PR_GLOBAL_BOUND_THREAD))
							&& _PR_IS_NATIVE_THREAD_SUPPORTED());

    _PR_ADJUST_STACKSIZE(stackSize);

    if (native) {
    /*
     * clear the IDLE_THREAD flag which applies to LOCAL
     * threads only
     */
    flags &= ~_PR_IDLE_THREAD;
        flags |= _PR_GLOBAL_SCOPE;
        if (_PR_NUM_DEADNATIVE > 0) {
            _PR_DEADQ_LOCK;

            if (_PR_NUM_DEADNATIVE == 0) { /* Thread safe check */
                _PR_DEADQ_UNLOCK;
            } else {
                thread = _PR_THREAD_PTR(_PR_DEADNATIVEQ.next);
                PR_REMOVE_LINK(&thread->links);
                _PR_DEC_DEADNATIVE;
                _PR_DEADQ_UNLOCK;

                _PR_InitializeRecycledThread(thread);
                thread->startFunc = start;
                thread->arg = arg;
            thread->flags = (flags | _PR_GLOBAL_SCOPE);
            if (type == PR_SYSTEM_THREAD)
            {
                thread->flags |= _PR_SYSTEM;
                PR_ATOMIC_INCREMENT(&_pr_systemActive);
            }
            else PR_ATOMIC_INCREMENT(&_pr_userActive);

            if (state == PR_JOINABLE_THREAD) {
                if (!thread->term) 
                       thread->term = PR_NewCondVar(_pr_terminationCVLock);
            }
        else {
                if(thread->term) {
                    PR_DestroyCondVar(thread->term);
                        thread->term = 0;
            }
            }

                thread->priority = priority;
        _PR_MD_SET_PRIORITY(&(thread->md), priority);
        /* XXX what about stackSize? */
        thread->state = _PR_RUNNING;
                _PR_MD_WAKEUP_WAITER(thread);
        return thread;
            }
        }
        thread = _PR_NativeCreateThread(type, start, arg, priority, 
                                            scope, state, stackSize, flags);
    } else {
        if (_PR_NUM_DEADUSER > 0) {
            _PR_DEADQ_LOCK;

            if (_PR_NUM_DEADUSER == 0) {  /* thread safe check */
                _PR_DEADQ_UNLOCK;
            } else {
                PRCList *ptr;

                /* Go down list checking for a recycled thread with a 
                 * large enough stack.  XXXMB - this has a bad degenerate case.
                 */
                ptr = _PR_DEADUSERQ.next;
                while( ptr != &_PR_DEADUSERQ ) {
                    thread = _PR_THREAD_PTR(ptr);
                    if ((thread->stack->stackSize >= stackSize) &&
                (!thread->no_sched)) {
                        PR_REMOVE_LINK(&thread->links);
                        _PR_DEC_DEADUSER;
                        break;
                    } else {
                        ptr = ptr->next;
                        thread = NULL;
                    }
                } 

                _PR_DEADQ_UNLOCK;

               if (thread) {
                    _PR_InitializeRecycledThread(thread);
                    thread->startFunc = start;
                    thread->arg = arg;
                    thread->priority = priority;
            if (state == PR_JOINABLE_THREAD) {
            if (!thread->term) 
               thread->term = PR_NewCondVar(_pr_terminationCVLock);
            } else {
            if(thread->term) {
               PR_DestroyCondVar(thread->term);
                thread->term = 0;
            }
            }
                    useRecycled++;
                }
            }
        } 
        if (thread == NULL) {
#ifndef HAVE_CUSTOM_USER_THREADS
            stack = _PR_NewStack(stackSize);
            if (!stack) {
                PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
                return NULL;
            }

            /* Allocate thread object and per-thread data off the top of the stack*/
            top = stack->stackTop;
#ifdef HAVE_STACK_GROWING_UP
            thread = (PRThread*) top;
            top = top + sizeof(PRThread);
            /*
             * Make stack 64-byte aligned
             */
            if ((PRUptrdiff)top & 0x3f) {
                top = (char*)(((PRUptrdiff)top + 0x40) & ~0x3f);
            }
#else
            top = top - sizeof(PRThread);
            thread = (PRThread*) top;
            /*
             * Make stack 64-byte aligned
             */
            if ((PRUptrdiff)top & 0x3f) {
                top = (char*)((PRUptrdiff)top & ~0x3f);
            }
#endif
            stack->thr = thread;
            memset(thread, 0, sizeof(PRThread));
            thread->threadAllocatedOnStack = 1;
#else
            thread = _PR_MD_CREATE_USER_THREAD(stackSize, start, arg);
            if (!thread) {
                PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
                return NULL;
            }
            thread->threadAllocatedOnStack = 0;
            stack = NULL;
            top = NULL;
#endif

            /* Initialize thread */
            thread->tpdLength = 0;
            thread->privateData = NULL;
            thread->stack = stack;
            thread->priority = priority;
            thread->startFunc = start;
            thread->arg = arg;
            PR_INIT_CLIST(&thread->lockList);

            if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
                if (thread->threadAllocatedOnStack == 1)
                    _PR_FreeStack(thread->stack);
                else {
                    PR_DELETE(thread);
                }
                PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
                return NULL;
            }

            if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {
                if (thread->threadAllocatedOnStack == 1)
                    _PR_FreeStack(thread->stack);
                else {
                    PR_DELETE(thread->privateData);
                    PR_DELETE(thread);
                }
                PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
                return NULL;
            }

            _PR_MD_INIT_CONTEXT(thread, top, _PR_UserRunThread, &status);

            if (status == PR_FALSE) {
                _PR_MD_FREE_LOCK(&thread->threadLock);
                if (thread->threadAllocatedOnStack == 1)
                    _PR_FreeStack(thread->stack);
                else {
                    PR_DELETE(thread->privateData);
                    PR_DELETE(thread);
                }
                return NULL;
            }

            /* 
              Set thread flags related to scope and joinable state. If joinable
              thread, allocate a "termination" condition variable.
            */
            if (state == PR_JOINABLE_THREAD) {
                thread->term = PR_NewCondVar(_pr_terminationCVLock);
                if (thread->term == NULL) {
                    _PR_MD_FREE_LOCK(&thread->threadLock);
                    if (thread->threadAllocatedOnStack == 1)
                        _PR_FreeStack(thread->stack);
                    else {
                        PR_DELETE(thread->privateData);
                        PR_DELETE(thread);
                    }
                    return NULL;
                }
            }
  
        }
  
        /* Update thread type counter */
        PR_Lock(_pr_activeLock);
        thread->flags = flags;
        thread->id = ++_pr_utid;
        if (type == PR_SYSTEM_THREAD) {
            thread->flags |= _PR_SYSTEM;
            _pr_systemActive++;
        } else {
            _pr_userActive++;
        }

        /* Make thread runnable */
        thread->state = _PR_RUNNABLE;
    /*
     * Add to list of active threads
     */
        PR_Unlock(_pr_activeLock);

        if ((! (thread->flags & _PR_IDLE_THREAD)) && _PR_IS_NATIVE_THREAD(me) )
            thread->cpu = _PR_GetPrimordialCPU();
        else
            thread->cpu = _PR_MD_CURRENT_CPU();

        PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));

        if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me)) {
            _PR_INTSOFF(is);
            _PR_RUNQ_LOCK(thread->cpu);
            _PR_ADD_RUNQ(thread, thread->cpu, priority);
            _PR_RUNQ_UNLOCK(thread->cpu);
        }

        if (thread->flags & _PR_IDLE_THREAD) {
            /*
            ** If the creating thread is a kernel thread, we need to
            ** awaken the user thread idle thread somehow; potentially
            ** it could be sleeping in its idle loop, and we need to poke
            ** it.  To do so, wake the idle thread...  
            */
            _PR_MD_WAKEUP_WAITER(NULL);
        } else if (_PR_IS_NATIVE_THREAD(me)) {
            _PR_MD_WAKEUP_WAITER(thread);
        }
        if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me) )
            _PR_INTSON(is);
    }

    return thread;
}

PR_IMPLEMENT(PRThread*) PR_CreateThread(PRThreadType type,
                     void (*start)(void *arg),
                     void *arg,
                     PRThreadPriority priority,
                     PRThreadScope scope,
                     PRThreadState state,
                     PRUint32 stackSize)
{
    return _PR_CreateThread(type, start, arg, priority, scope, state, 
                            stackSize, 0);
}

/*
** Associate a thread object with an existing native thread.
**     "type" is the type of thread object to attach
**     "priority" is the priority to assign to the thread
**     "stack" defines the shape of the threads stack
**
** This can return NULL if some kind of error occurs, or if memory is
** tight.
**
** This call is not normally needed unless you create your own native
** thread. PR_Init does this automatically for the primordial thread.
*/
PRThread* _PRI_AttachThread(PRThreadType type,
    PRThreadPriority priority, PRThreadStack *stack, PRUint32 flags)
{
    PRThread *thread;

    if ((thread = _PR_MD_GET_ATTACHED_THREAD()) != NULL) {
        return thread;
    }
    _PR_MD_SET_CURRENT_THREAD(NULL);

    /* Clear out any state if this thread was attached before */
    _PR_MD_SET_CURRENT_CPU(NULL);

    thread = _PR_AttachThread(type, priority, stack);
    if (thread) {
        PRIntn is;

        _PR_MD_SET_CURRENT_THREAD(thread);

        thread->flags = flags | _PR_GLOBAL_SCOPE | _PR_ATTACHED;

        if (!stack) {
            thread->stack = PR_NEWZAP(PRThreadStack);
            if (!thread->stack) {
                _PR_DestroyThread(thread);
                return NULL;
            }
            thread->stack->stackSize = _MD_DEFAULT_STACK_SIZE;
        }
        PR_INIT_CLIST(&thread->links);

        if (_PR_MD_INIT_ATTACHED_THREAD(thread) == PR_FAILURE) {
                PR_DELETE(thread->stack);
                _PR_DestroyThread(thread);
                return NULL;
        }

        _PR_MD_SET_CURRENT_CPU(NULL);

        if (_PR_MD_CURRENT_CPU()) {
            _PR_INTSOFF(is);
            PR_Lock(_pr_activeLock);
        }
        if (type == PR_SYSTEM_THREAD) {
            thread->flags |= _PR_SYSTEM;
            _pr_systemActive++;
        } else {
            _pr_userActive++;
        }
        if (_PR_MD_CURRENT_CPU()) {
            PR_Unlock(_pr_activeLock);
            _PR_INTSON(is);
        }
    }
    return thread;
}

PR_IMPLEMENT(PRThread*) PR_AttachThread(PRThreadType type,
    PRThreadPriority priority, PRThreadStack *stack)
{
    return PR_GetCurrentThread();
}

PR_IMPLEMENT(void) PR_DetachThread(void)
{
    /*
     * On IRIX, Solaris, and Windows, foreign threads are detached when
     * they terminate.
     */
#if !defined(IRIX) && !defined(WIN32) \
        && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY))
    PRThread *me;
    if (_pr_initialized) {
        me = _PR_MD_GET_ATTACHED_THREAD();
        if ((me != NULL) && (me->flags & _PR_ATTACHED))
            _PRI_DetachThread();
    }
#endif
}

void _PRI_DetachThread(void)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();

	if (me->flags & _PR_PRIMORDIAL) {
		/*
		 * ignore, if primordial thread
		 */
		return;
	}
    PR_ASSERT(me->flags & _PR_ATTACHED);
    PR_ASSERT(_PR_IS_NATIVE_THREAD(me));
    _PR_CleanupThread(me);
    PR_DELETE(me->privateData);

    _PR_DecrActiveThreadCount(me);

    _PR_MD_CLEAN_THREAD(me);
    _PR_MD_SET_CURRENT_THREAD(NULL);
    if (!me->threadAllocatedOnStack) 
        PR_DELETE(me->stack);
    _PR_MD_FREE_LOCK(&me->threadLock);
    PR_DELETE(me);
}

/*
** Wait for thread termination:
**     "thread" is the target thread 
**
** This can return PR_FAILURE if no joinable thread could be found 
** corresponding to the specified target thread.
**
** The calling thread is suspended until the target thread completes.
** Several threads cannot wait for the same thread to complete; one thread
** will complete successfully and others will terminate with an error PR_FAILURE.
** The calling thread will not be blocked if the target thread has already
** terminated.
*/
PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thread)
{
    PRIntn is;
    PRCondVar *term;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if (!_PR_IS_NATIVE_THREAD(me))
        _PR_INTSOFF(is);
    term = thread->term;
    /* can't join a non-joinable thread */
    if (term == NULL) {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        goto ErrorExit;
    }

    /* multiple threads can't wait on the same joinable thread */
    if (term->condQ.next != &term->condQ) {
        goto ErrorExit;
    }
    if (!_PR_IS_NATIVE_THREAD(me))
        _PR_INTSON(is);

    /* wait for the target thread's termination cv invariant */
    PR_Lock (_pr_terminationCVLock);
    while (thread->state != _PR_JOIN_WAIT) {
        (void) PR_WaitCondVar(term, PR_INTERVAL_NO_TIMEOUT);
    }
    (void) PR_Unlock (_pr_terminationCVLock);
    
    /* 
     Remove target thread from global waiting to join Q; make it runnable
     again and put it back on its run Q.  When it gets scheduled later in
     _PR_RunThread code, it will clean up its stack.
    */    
    if (!_PR_IS_NATIVE_THREAD(me))
        _PR_INTSOFF(is);
    thread->state = _PR_RUNNABLE;
    if ( !_PR_IS_NATIVE_THREAD(thread) ) {
        _PR_THREAD_LOCK(thread);

        _PR_MISCQ_LOCK(thread->cpu);
        _PR_DEL_JOINQ(thread);
        _PR_MISCQ_UNLOCK(thread->cpu);

        _PR_AddThreadToRunQ(me, thread);
        _PR_THREAD_UNLOCK(thread);
    }
    if (!_PR_IS_NATIVE_THREAD(me))
        _PR_INTSON(is);

    _PR_MD_WAKEUP_WAITER(thread);

    return PR_SUCCESS;

ErrorExit:
    if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
    return PR_FAILURE;   
}

PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thread,
    PRThreadPriority newPri)
{

    /* 
    First, pin down the priority.  Not all compilers catch passing out of
    range enum here.  If we let bad values thru, priority queues won't work.
    */
    if ((PRIntn)newPri > (PRIntn)PR_PRIORITY_LAST) {
        newPri = PR_PRIORITY_LAST;
    } else if ((PRIntn)newPri < (PRIntn)PR_PRIORITY_FIRST) {
        newPri = PR_PRIORITY_FIRST;
    }
        
    if ( _PR_IS_NATIVE_THREAD(thread) ) {
        thread->priority = newPri;
        _PR_MD_SET_PRIORITY(&(thread->md), newPri);
    } else _PR_SetThreadPriority(thread, newPri);
}


/*
** This routine prevents all other threads from running. This call is needed by 
** the garbage collector.
*/
PR_IMPLEMENT(void) PR_SuspendAll(void)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRCList *qp;

    /*
     * Stop all user and native threads which are marked GC able.
     */
    PR_Lock(_pr_activeLock);
    suspendAllOn = PR_TRUE;
    suspendAllThread = _PR_MD_CURRENT_THREAD();
    _PR_MD_BEGIN_SUSPEND_ALL();
    for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
        qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
        if ((me != _PR_ACTIVE_THREAD_PTR(qp)) && 
            _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp))) {
            _PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp));
                PR_ASSERT((_PR_ACTIVE_THREAD_PTR(qp))->state != _PR_RUNNING);
            }
    }
    for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
        qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
        if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
            _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp)))
            /* PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp)); */
                _PR_MD_SUSPEND_THREAD(_PR_ACTIVE_THREAD_PTR(qp)); 
    }
    _PR_MD_END_SUSPEND_ALL();
}

/*
** This routine unblocks all other threads that were suspended from running by 
** PR_SuspendAll(). This call is needed by the garbage collector.
*/
PR_IMPLEMENT(void) PR_ResumeAll(void)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRCList *qp;

    /*
     * Resume all user and native threads which are marked GC able.
     */
    _PR_MD_BEGIN_RESUME_ALL();
    for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
        qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
        if ((me != _PR_ACTIVE_THREAD_PTR(qp)) && 
            _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp)))
            _PR_Resume(_PR_ACTIVE_THREAD_PTR(qp));
    }
    for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
        qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
        if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
            _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp)))
                _PR_MD_RESUME_THREAD(_PR_ACTIVE_THREAD_PTR(qp));
    }
    _PR_MD_END_RESUME_ALL();
    suspendAllThread = NULL;
    suspendAllOn = PR_FALSE;
    PR_Unlock(_pr_activeLock);
}

PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
{
    PRCList *qp, *qp_next;
    PRIntn i = 0;
    PRStatus rv = PR_SUCCESS;
    PRThread* t;

    /*
    ** Currently Enumerate threads happen only with suspension and
    ** pr_activeLock held
    */
    PR_ASSERT(suspendAllOn);

    /* Steve Morse, 4-23-97: Note that we can't walk a queue by taking
     * qp->next after applying the function "func".  In particular, "func"
     * might remove the thread from the queue and put it into another one in
     * which case qp->next no longer points to the next entry in the original
     * queue.
     *
     * To get around this problem, we save qp->next in qp_next before applying
     * "func" and use that saved value as the next value after applying "func".
     */

    /*
     * Traverse the list of local and global threads
     */
    for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
         qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp_next)
    {
        qp_next = qp->next;
        t = _PR_ACTIVE_THREAD_PTR(qp);
        if (_PR_IS_GCABLE_THREAD(t))
        {
            rv = (*func)(t, i, arg);
            if (rv != PR_SUCCESS)
                return rv;
            i++;
        }
    }
    for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
         qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp_next)
    {
        qp_next = qp->next;
        t = _PR_ACTIVE_THREAD_PTR(qp);
        if (_PR_IS_GCABLE_THREAD(t))
        {
            rv = (*func)(t, i, arg);
            if (rv != PR_SUCCESS)
                return rv;
            i++;
        }
    }
    return rv;
}

/* FUNCTION: _PR_AddSleepQ
** DESCRIPTION:
**    Adds a thread to the sleep/pauseQ.
** RESTRICTIONS:
**    Caller must have the RUNQ lock.
**    Caller must be a user level thread
*/
PR_IMPLEMENT(void)
_PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout)
{
    _PRCPU *cpu = thread->cpu;

    if (timeout == PR_INTERVAL_NO_TIMEOUT) {
        /* append the thread to the global pause Q */
        PR_APPEND_LINK(&thread->links, &_PR_PAUSEQ(thread->cpu));
        thread->flags |= _PR_ON_PAUSEQ;
    } else {
        PRIntervalTime sleep;
        PRCList *q;
        PRThread *t;

        /* sort onto global sleepQ */
        sleep = timeout;

        /* Check if we are longest timeout */
        if (timeout >= _PR_SLEEPQMAX(cpu)) {
            PR_INSERT_BEFORE(&thread->links, &_PR_SLEEPQ(cpu));
            thread->sleep = timeout - _PR_SLEEPQMAX(cpu);
            _PR_SLEEPQMAX(cpu) = timeout;
        } else {
            /* Sort thread into global sleepQ at appropriate point */
            q = _PR_SLEEPQ(cpu).next;

            /* Now scan the list for where to insert this entry */
            while (q != &_PR_SLEEPQ(cpu)) {
                t = _PR_THREAD_PTR(q);
                if (sleep < t->sleep) {
                    /* Found sleeper to insert in front of */
                    break;
                }
                sleep -= t->sleep;
                q = q->next;
            }
            thread->sleep = sleep;
            PR_INSERT_BEFORE(&thread->links, q);

            /*
            ** Subtract our sleep time from the sleeper that follows us (there
            ** must be one) so that they remain relative to us.
            */
            PR_ASSERT (thread->links.next != &_PR_SLEEPQ(cpu));
          
            t = _PR_THREAD_PTR(thread->links.next);
            PR_ASSERT(_PR_THREAD_PTR(t->links.prev) == thread);
            t->sleep -= sleep;
        }

        thread->flags |= _PR_ON_SLEEPQ;
    }
}

/* FUNCTION: _PR_DelSleepQ
** DESCRIPTION:
**    Removes a thread from the sleep/pauseQ.
** INPUTS:
**    If propogate_time is true, then the thread following the deleted
**    thread will be get the time from the deleted thread.  This is used
**    when deleting a sleeper that has not timed out.
** RESTRICTIONS:
**    Caller must have the RUNQ lock.
**    Caller must be a user level thread
*/
PR_IMPLEMENT(void)
_PR_DelSleepQ(PRThread *thread, PRBool propogate_time)
{
    _PRCPU *cpu = thread->cpu;

    /* Remove from pauseQ/sleepQ */
    if (thread->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
        if (thread->flags & _PR_ON_SLEEPQ) {
            PRCList *q = thread->links.next;
            if (q != &_PR_SLEEPQ(cpu)) {
                if (propogate_time == PR_TRUE) {
                    PRThread *after = _PR_THREAD_PTR(q);
                    after->sleep += thread->sleep;
                } else 
                    _PR_SLEEPQMAX(cpu) -= thread->sleep;
            } else {
                /* Check if prev is the beggining of the list; if so,
                 * we are the only element on the list.  
                 */
                if (thread->links.prev != &_PR_SLEEPQ(cpu))
                    _PR_SLEEPQMAX(cpu) -= thread->sleep;
                else
                    _PR_SLEEPQMAX(cpu) = 0;
            }
            thread->flags &= ~_PR_ON_SLEEPQ;
        } else {
            thread->flags &= ~_PR_ON_PAUSEQ;
        }
        PR_REMOVE_LINK(&thread->links);
    } else 
        PR_ASSERT(0);
}

void
_PR_AddThreadToRunQ(
    PRThread *me,     /* the current thread */
    PRThread *thread) /* the local thread to be added to a run queue */
{
    PRThreadPriority pri = thread->priority;
    _PRCPU *cpu = thread->cpu;

    PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));

#if defined(WINNT)
    /*
     * On NT, we can only reliably know that the current CPU
     * is not idle.  We add the awakened thread to the run
     * queue of its CPU if its CPU is the current CPU.
     * For any other CPU, we don't really know whether it
     * is busy or idle.  So in all other cases, we just
     * "post" the awakened thread to the IO completion port
     * for the next idle CPU to execute (this is done in
     * _PR_MD_WAKEUP_WAITER).
	 * Threads with a suspended I/O operation remain bound to
	 * the same cpu until I/O is cancelled
     *
     * NOTE: the boolean expression below must be the exact
     * opposite of the corresponding boolean expression in
     * _PR_MD_WAKEUP_WAITER.
     */
    if ((!_PR_IS_NATIVE_THREAD(me) && (cpu == me->cpu)) ||
					(thread->md.thr_bound_cpu)) {
		PR_ASSERT(!thread->md.thr_bound_cpu ||
							(thread->md.thr_bound_cpu == cpu));
        _PR_RUNQ_LOCK(cpu);
        _PR_ADD_RUNQ(thread, cpu, pri);
        _PR_RUNQ_UNLOCK(cpu);
    }
#else
    _PR_RUNQ_LOCK(cpu);
    _PR_ADD_RUNQ(thread, cpu, pri);
    _PR_RUNQ_UNLOCK(cpu);
    if (!_PR_IS_NATIVE_THREAD(me) && (cpu == me->cpu)) {
        if (pri > me->priority) {
            _PR_SET_RESCHED_FLAG();
        }
    }
#endif
}

deps/mozilla/nsprpub/pr/src/threads/prcmon.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

#include <stdlib.h>
#include <stddef.h>

/* Lock used to lock the monitor cache */
#ifdef _PR_NO_PREEMPT
#define _PR_NEW_LOCK_MCACHE()
#define _PR_DESTROY_LOCK_MCACHE()
#define _PR_LOCK_MCACHE()
#define _PR_UNLOCK_MCACHE()
#else
#ifdef _PR_LOCAL_THREADS_ONLY
#define _PR_NEW_LOCK_MCACHE()
#define _PR_DESTROY_LOCK_MCACHE()
#define _PR_LOCK_MCACHE() { PRIntn _is; _PR_INTSOFF(_is)
#define _PR_UNLOCK_MCACHE() _PR_INTSON(_is); }
#else
PRLock *_pr_mcacheLock;
#define _PR_NEW_LOCK_MCACHE() (_pr_mcacheLock = PR_NewLock())
#define _PR_DESTROY_LOCK_MCACHE()               \
    PR_BEGIN_MACRO                              \
        if (_pr_mcacheLock) {                   \
            PR_DestroyLock(_pr_mcacheLock);     \
            _pr_mcacheLock = NULL;              \
        }                                       \
    PR_END_MACRO
#define _PR_LOCK_MCACHE() PR_Lock(_pr_mcacheLock)
#define _PR_UNLOCK_MCACHE() PR_Unlock(_pr_mcacheLock)
#endif
#endif

/************************************************************************/

typedef struct MonitorCacheEntryStr MonitorCacheEntry;

struct MonitorCacheEntryStr {
    MonitorCacheEntry*  next;
    void*               address;
    PRMonitor*          mon;
    long                cacheEntryCount;
};

/*
** An array of MonitorCacheEntry's, plus a pointer to link these
** arrays together.
*/

typedef struct MonitorCacheEntryBlockStr MonitorCacheEntryBlock;

struct MonitorCacheEntryBlockStr {
    MonitorCacheEntryBlock* next;
    MonitorCacheEntry entries[1];
};

static PRUint32 hash_mask;
static PRUintn num_hash_buckets;
static PRUintn num_hash_buckets_log2;
static MonitorCacheEntry **hash_buckets;
static MonitorCacheEntry *free_entries;
static PRUintn num_free_entries;
static PRBool expanding;
static MonitorCacheEntryBlock *mcache_blocks;

static void (*OnMonitorRecycle)(void *address);

#define HASH(address)                               \
    ((PRUint32) ( ((PRUptrdiff)(address) >> 2) ^    \
                  ((PRUptrdiff)(address) >> 10) )   \
     & hash_mask)

/*
** Expand the monitor cache. This grows the hash buckets and allocates a
** new chunk of cache entries and throws them on the free list. We keep
** as many hash buckets as there are entries.
**
** Because we call malloc and malloc may need the monitor cache, we must
** ensure that there are several free monitor cache entries available for
** malloc to get. FREE_THRESHOLD is used to prevent monitor cache
** starvation during monitor cache expansion.
*/

#define FREE_THRESHOLD  5

static PRStatus ExpandMonitorCache(PRUintn new_size_log2)
{
    MonitorCacheEntry **old_hash_buckets, *p;
    PRUintn i, entries, old_num_hash_buckets, added;
    MonitorCacheEntry **new_hash_buckets;
    MonitorCacheEntryBlock *new_block;

    entries = 1L << new_size_log2;

    /*
    ** Expand the monitor-cache-entry free list
    */
    new_block = (MonitorCacheEntryBlock*)
        PR_CALLOC(sizeof(MonitorCacheEntryBlock)
        + (entries - 1) * sizeof(MonitorCacheEntry));
    if (NULL == new_block) return PR_FAILURE;

    /*
    ** Allocate system monitors for the new monitor cache entries. If we
    ** run out of system monitors, break out of the loop.
    */
    for (i = 0, p = new_block->entries; i < entries; i++, p++) {
        p->mon = PR_NewMonitor();
        if (!p->mon)
            break;
    }
    added = i;
    if (added != entries) {
        MonitorCacheEntryBlock *realloc_block;

        if (added == 0) {
            /* Totally out of system monitors. Lossage abounds */
            PR_DELETE(new_block);
            return PR_FAILURE;
        }

        /*
        ** We were able to allocate some of the system monitors. Use
        ** realloc to shrink down the new_block memory. If that fails,
        ** carry on with the too-large new_block.
        */
        realloc_block = (MonitorCacheEntryBlock*)
            PR_REALLOC(new_block, sizeof(MonitorCacheEntryBlock)
            + (added - 1) * sizeof(MonitorCacheEntry));
        if (realloc_block)
            new_block = realloc_block;
    }

    /*
    ** Now that we have allocated all of the system monitors, build up
    ** the new free list. We can just update the free_list because we own
    ** the mcache-lock and we aren't calling anyone who might want to use
    ** it.
    */
    for (i = 0, p = new_block->entries; i < added - 1; i++, p++)
        p->next = p + 1;
    p->next = free_entries;
    free_entries = new_block->entries;
    num_free_entries += added;
    new_block->next = mcache_blocks;
    mcache_blocks = new_block;

    /* Try to expand the hash table */
    new_hash_buckets = (MonitorCacheEntry**)
        PR_CALLOC(entries * sizeof(MonitorCacheEntry*));
    if (NULL == new_hash_buckets) {
        /*
        ** Partial lossage. In this situation we don't get any more hash
        ** buckets, which just means that the table lookups will take
        ** longer. This is bad, but not fatal
        */
        PR_LOG(_pr_cmon_lm, PR_LOG_WARNING,
               ("unable to grow monitor cache hash buckets"));
        return PR_SUCCESS;
    }

    /*
    ** Compute new hash mask value. This value is used to mask an address
    ** until it's bits are in the right spot for indexing into the hash
    ** table.
    */
    hash_mask = entries - 1;

    /*
    ** Expand the hash table. We have to rehash everything in the old
    ** table into the new table.
    */
    old_hash_buckets = hash_buckets;
    old_num_hash_buckets = num_hash_buckets;
    for (i = 0; i < old_num_hash_buckets; i++) {
        p = old_hash_buckets[i];
        while (p) {
            MonitorCacheEntry *next = p->next;

            /* Hash based on new table size, and then put p in the new table */
            PRUintn hash = HASH(p->address);
            p->next = new_hash_buckets[hash];
            new_hash_buckets[hash] = p;

            p = next;
        }
    }

    /*
    ** Switch over to new hash table and THEN call free of the old
    ** table. Since free might re-enter _pr_mcache_lock, things would
    ** break terribly if it used the old hash table.
    */
    hash_buckets = new_hash_buckets;
    num_hash_buckets = entries;
    num_hash_buckets_log2 = new_size_log2;
    PR_DELETE(old_hash_buckets);

    PR_LOG(_pr_cmon_lm, PR_LOG_NOTICE,
           ("expanded monitor cache to %d (buckets %d)",
            num_free_entries, entries));

    return PR_SUCCESS;
}  /* ExpandMonitorCache */

/*
** Lookup a monitor cache entry by address. Return a pointer to the
** pointer to the monitor cache entry on success, null on failure.
*/
static MonitorCacheEntry **LookupMonitorCacheEntry(void *address)
{
    PRUintn hash;
    MonitorCacheEntry **pp, *p;

    hash = HASH(address);
    pp = hash_buckets + hash;
    while ((p = *pp) != 0) {
        if (p->address == address) {
            if (p->cacheEntryCount > 0)
                return pp;
            return NULL;
        }
        pp = &p->next;
    }
    return NULL;
}

/*
** Try to create a new cached monitor. If it's already in the cache,
** great - return it. Otherwise get a new free cache entry and set it
** up. If the cache free space is getting low, expand the cache.
*/
static PRMonitor *CreateMonitor(void *address)
{
    PRUintn hash;
    MonitorCacheEntry **pp, *p;

    hash = HASH(address);
    pp = hash_buckets + hash;
    while ((p = *pp) != 0) {
        if (p->address == address) goto gotit;

        pp = &p->next;
    }

    /* Expand the monitor cache if we have run out of free slots in the table */
    if (num_free_entries < FREE_THRESHOLD) {
        /* Expand monitor cache */

        /*
        ** This function is called with the lock held. So what's the 'expanding'
        ** boolean all about? Seems a bit redundant.
        */
        if (!expanding) {
            PRStatus rv;

            expanding = PR_TRUE;
            rv = ExpandMonitorCache(num_hash_buckets_log2 + 1);
            expanding = PR_FALSE;
            if (PR_FAILURE == rv)  return NULL;

            /* redo the hash because it'll be different now */
            hash = HASH(address);
        } else {
            /*
            ** We are in process of expanding and we need a cache
            ** monitor.  Make sure we have enough!
            */
            PR_ASSERT(num_free_entries > 0);
        }
    }

    /* Make a new monitor */
    p = free_entries;
    free_entries = p->next;
    num_free_entries--;
    if (OnMonitorRecycle && p->address)
        OnMonitorRecycle(p->address);
    p->address = address;
    p->next = hash_buckets[hash];
    hash_buckets[hash] = p;
    PR_ASSERT(p->cacheEntryCount == 0);

  gotit:
    p->cacheEntryCount++;
    return p->mon;
}

/*
** Initialize the monitor cache
*/
void _PR_InitCMon(void)
{
    _PR_NEW_LOCK_MCACHE();
    ExpandMonitorCache(3);
}

/*
** Destroy the monitor cache
*/
void _PR_CleanupCMon(void)
{
    _PR_DESTROY_LOCK_MCACHE();

    while (free_entries) {
        PR_DestroyMonitor(free_entries->mon);
        free_entries = free_entries->next;
    }
    num_free_entries = 0;

    while (mcache_blocks) {
        MonitorCacheEntryBlock *block;

        block = mcache_blocks;
        mcache_blocks = block->next;
        PR_DELETE(block);
    }

    PR_DELETE(hash_buckets);
    hash_mask = 0;
    num_hash_buckets = 0;
    num_hash_buckets_log2 = 0;

    expanding = PR_FALSE;
    OnMonitorRecycle = NULL;
}

/*
** Create monitor for address. Don't enter the monitor while we have the
** mcache locked because we might block!
*/
PR_IMPLEMENT(PRMonitor*) PR_CEnterMonitor(void *address)
{
    PRMonitor *mon;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    _PR_LOCK_MCACHE();
    mon = CreateMonitor(address);
    _PR_UNLOCK_MCACHE();

    if (!mon) return NULL;

    PR_EnterMonitor(mon);
    return mon;
}

PR_IMPLEMENT(PRStatus) PR_CExitMonitor(void *address)
{
    MonitorCacheEntry **pp, *p;
    PRStatus status = PR_SUCCESS;

    _PR_LOCK_MCACHE();
    pp = LookupMonitorCacheEntry(address);
    if (pp != NULL) {
        p = *pp;
        if (--p->cacheEntryCount == 0) {
            /*
            ** Nobody is using the system monitor. Put it on the cached free
            ** list. We are safe from somebody trying to use it because we
            ** have the mcache locked.
            */
            p->address = 0;             /* defensive move */
            *pp = p->next;              /* unlink from hash_buckets */
            p->next = free_entries;     /* link into free list */
            free_entries = p;
            num_free_entries++;         /* count it as free */
        }
        status = PR_ExitMonitor(p->mon);
    } else {
        status = PR_FAILURE;
    }
    _PR_UNLOCK_MCACHE();

    return status;
}

PR_IMPLEMENT(PRStatus) PR_CWait(void *address, PRIntervalTime ticks)
{
    MonitorCacheEntry **pp;
    PRMonitor *mon;

    _PR_LOCK_MCACHE();
    pp = LookupMonitorCacheEntry(address);
    mon = pp ? ((*pp)->mon) : NULL;
    _PR_UNLOCK_MCACHE();

    if (mon == NULL)
        return PR_FAILURE;
    return PR_Wait(mon, ticks);
}

PR_IMPLEMENT(PRStatus) PR_CNotify(void *address)
{
    MonitorCacheEntry **pp;
    PRMonitor *mon;

    _PR_LOCK_MCACHE();
    pp = LookupMonitorCacheEntry(address);
    mon = pp ? ((*pp)->mon) : NULL;
    _PR_UNLOCK_MCACHE();

    if (mon == NULL)
        return PR_FAILURE;
    return PR_Notify(mon);
}

PR_IMPLEMENT(PRStatus) PR_CNotifyAll(void *address)
{
    MonitorCacheEntry **pp;
    PRMonitor *mon;

    _PR_LOCK_MCACHE();
    pp = LookupMonitorCacheEntry(address);
    mon = pp ? ((*pp)->mon) : NULL;
    _PR_UNLOCK_MCACHE();

    if (mon == NULL)
        return PR_FAILURE;
    return PR_NotifyAll(mon);
}

PR_IMPLEMENT(void)
PR_CSetOnMonitorRecycle(void (*callback)(void *address))
{
    OnMonitorRecycle = callback;
}

deps/mozilla/nsprpub/pr/src/threads/prcthr.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

#if defined(WIN95)
/*
** Some local variables report warnings on Win95 because the code paths 
** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
** The pragma suppresses the warning.
** 
*/
#pragma warning(disable : 4101)
#endif


extern PRLock *_pr_sleeplock;  /* allocated and initialized in prinit */
/* 
** Routines common to both native and user threads.
**
**
** Clean up a thread object, releasing all of the attached data. Do not
** free the object itself (it may not have been malloc'd)
*/
void _PR_CleanupThread(PRThread *thread)
{
    /* Free up per-thread-data */
    _PR_DestroyThreadPrivate(thread);

    /* Free any thread dump procs */
    if (thread->dumpArg) {
        PR_DELETE(thread->dumpArg);
    }
    thread->dump = 0;

    PR_DELETE(thread->errorString);
    thread->errorStringSize = 0;
    thread->errorStringLength = 0;
    thread->environment = NULL;
}

PR_IMPLEMENT(PRStatus) PR_Yield()
{
    static PRBool warning = PR_TRUE;
    if (warning) warning = _PR_Obsolete(
        "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)");
    return (PR_Sleep(PR_INTERVAL_NO_WAIT));
}

/*
** Make the current thread sleep until "timeout" ticks amount of time
** has expired. If "timeout" is PR_INTERVAL_NO_WAIT then the call is
** equivalent to a yield. Waiting for an infinite amount of time is
** allowed in the expectation that another thread will interrupt().
**
** A single lock is used for all threads calling sleep. Each caller
** does get its own condition variable since each is expected to have
** a unique 'timeout'.
*/
PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout)
{
    PRStatus rv = PR_SUCCESS;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (PR_INTERVAL_NO_WAIT == timeout)
    {
        /*
        ** This is a simple yield, nothing more, nothing less.
        */
        PRIntn is;
        PRThread *me = PR_GetCurrentThread();
        PRUintn pri = me->priority;
        _PRCPU *cpu = _PR_MD_CURRENT_CPU();

        if ( _PR_IS_NATIVE_THREAD(me) ) _PR_MD_YIELD();
        else
        {
            _PR_INTSOFF(is);
            _PR_RUNQ_LOCK(cpu);
            if (_PR_RUNQREADYMASK(cpu) >> pri) {
                me->cpu = cpu;
                me->state = _PR_RUNNABLE;
                _PR_ADD_RUNQ(me, cpu, pri);
                _PR_RUNQ_UNLOCK(cpu);

                PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: yielding"));
                _PR_MD_SWITCH_CONTEXT(me);
                PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: done"));

                _PR_FAST_INTSON(is);
            }
            else
            {
                _PR_RUNQ_UNLOCK(cpu);
                _PR_INTSON(is);
            }
        }
    }
    else
    {
        /*
        ** This is waiting for some finite period of time.
        ** A thread in this state is interruptible (PR_Interrupt()),
        ** but the lock and cvar used are local to the implementation
        ** and not visible to the caller, therefore not notifiable.
        */
        PRCondVar *cv;
        PRIntervalTime timein;

        timein = PR_IntervalNow();
        cv = PR_NewCondVar(_pr_sleeplock);
        PR_ASSERT(cv != NULL);
        PR_Lock(_pr_sleeplock);
        do
        {
            PRIntervalTime delta = PR_IntervalNow() - timein;
            if (delta > timeout) break;
            rv = PR_WaitCondVar(cv, timeout - delta);
        } while (rv == PR_SUCCESS);
        PR_Unlock(_pr_sleeplock);
        PR_DestroyCondVar(cv);
    }
    return rv;
}

PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thread)
{
    return thread->id;
}

PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread)
{
    return (PRThreadPriority) thread->priority;
}

PR_IMPLEMENT(PRThread *) PR_GetCurrentThread()
{
    if (!_pr_initialized) _PR_ImplicitInitialization();
    return _PR_MD_CURRENT_THREAD();
}

/*
** Set the interrupt flag for a thread. The thread will be unable to
** block in i/o functions when this happens. Also, any PR_Wait's in
** progress will be undone. The interrupt remains in force until
** PR_ClearInterrupt is called.
*/
PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thread)
{
#ifdef _PR_GLOBAL_THREADS_ONLY
    PRCondVar *victim;

    _PR_THREAD_LOCK(thread);
    thread->flags |= _PR_INTERRUPT;
    victim = thread->wait.cvar;
    _PR_THREAD_UNLOCK(thread);
    if ((NULL != victim) && (!(thread->flags & _PR_INTERRUPT_BLOCKED))) {
        int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD());

        if (!haveLock) PR_Lock(victim->lock);
        PR_NotifyAllCondVar(victim);
        if (!haveLock) PR_Unlock(victim->lock);
    }
    return PR_SUCCESS;
#else  /* ! _PR_GLOBAL_THREADS_ONLY */
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

            if (!_PR_IS_NATIVE_THREAD(me))
            	_PR_INTSOFF(is);

            _PR_THREAD_LOCK(thread);
            thread->flags |= _PR_INTERRUPT;
        switch (thread->state) {
                case _PR_COND_WAIT:
                        /*
                         * call is made with thread locked;
                         * on return lock is released
                         */
						if (!(thread->flags & _PR_INTERRUPT_BLOCKED))
                        	_PR_NotifyLockedThread(thread);
                        break;
                case _PR_IO_WAIT:
                        /*
                         * Need to hold the thread lock when calling
                         * _PR_Unblock_IO_Wait().  On return lock is
                         * released. 
                         */
#if defined(XP_UNIX) || defined(WINNT) || defined(WIN16)
						if (!(thread->flags & _PR_INTERRUPT_BLOCKED))
                        	_PR_Unblock_IO_Wait(thread);
#else
                        _PR_THREAD_UNLOCK(thread);
#endif
                        break;
                case _PR_RUNNING:
                case _PR_RUNNABLE:
                case _PR_LOCK_WAIT:
                default:
                            _PR_THREAD_UNLOCK(thread);
                        break;
        }
            if (!_PR_IS_NATIVE_THREAD(me))
            	_PR_INTSON(is);
            return PR_SUCCESS;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

/*
** Clear the interrupt flag for self.
*/
PR_IMPLEMENT(void) PR_ClearInterrupt()
{
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

        if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
    _PR_THREAD_LOCK(me);
         me->flags &= ~_PR_INTERRUPT;
    _PR_THREAD_UNLOCK(me);
        if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
}

PR_IMPLEMENT(void) PR_BlockInterrupt()
{
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
    _PR_THREAD_LOCK(me);
    _PR_THREAD_BLOCK_INTERRUPT(me);
    _PR_THREAD_UNLOCK(me);
    if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
}  /* PR_BlockInterrupt */

PR_IMPLEMENT(void) PR_UnblockInterrupt()
{
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
    _PR_THREAD_LOCK(me);
    _PR_THREAD_UNBLOCK_INTERRUPT(me);
    _PR_THREAD_UNLOCK(me);
    if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
}  /* PR_UnblockInterrupt */

/*
** Return the thread stack pointer of the given thread.
*/
PR_IMPLEMENT(void *) PR_GetSP(PRThread *thread)
{
        return (void *)_PR_MD_GET_SP(thread);
}

PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thread)
{
        return thread->environment;
}

PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thread, void *env)
{
        thread->environment = env;
}


PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask)
{
#ifdef HAVE_THREAD_AFFINITY
    return _PR_MD_GETTHREADAFFINITYMASK(thread, mask);
#else
    return 0;
#endif
}

PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask )
{
#ifdef HAVE_THREAD_AFFINITY
#ifndef IRIX
    return _PR_MD_SETTHREADAFFINITYMASK(thread, mask);
#else
	return 0;
#endif
#else
    return 0;
#endif
}

/* This call is thread unsafe if another thread is calling SetConcurrency()
 */
PR_IMPLEMENT(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask)
{
#ifdef HAVE_THREAD_AFFINITY
    PRCList *qp;
    extern PRUint32 _pr_cpu_affinity_mask;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    _pr_cpu_affinity_mask = mask;

    qp = _PR_CPUQ().next;
    while(qp != &_PR_CPUQ()) {
        _PRCPU *cpu;

        cpu = _PR_CPU_PTR(qp);
        PR_SetThreadAffinityMask(cpu->thread, mask);

        qp = qp->next;
    }
#endif

    return 0;
}

PRUint32 _pr_recycleThreads = 0;
PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 count)
{
    _pr_recycleThreads = count;
}

PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(PRThreadType type,
                                     void (*start)(void *arg),
                                     void *arg,
                                     PRThreadPriority priority,
                                     PRThreadScope scope,
                                     PRThreadState state,
                                     PRUint32 stackSize)
{
    return _PR_CreateThread(type, start, arg, priority, scope, state, 
                            stackSize, _PR_GCABLE_THREAD);
}

#ifdef SOLARIS
PR_IMPLEMENT(PRThread*) PR_CreateThreadBound(PRThreadType type,
                                     void (*start)(void *arg),
                                     void *arg,
                                     PRUintn priority,
                                     PRThreadScope scope,
                                     PRThreadState state,
                                     PRUint32 stackSize)
{
    return _PR_CreateThread(type, start, arg, priority, scope, state, 
                            stackSize, _PR_BOUND_THREAD);
}
#endif


PR_IMPLEMENT(PRThread*) PR_AttachThreadGCAble(
    PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
{
    /* $$$$ not sure how to finese this one */
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return NULL;
}

PR_IMPLEMENT(void) PR_SetThreadGCAble()
{
    if (!_pr_initialized) _PR_ImplicitInitialization();
    PR_Lock(_pr_activeLock);
        _PR_MD_CURRENT_THREAD()->flags |= _PR_GCABLE_THREAD;
        PR_Unlock(_pr_activeLock);        
}

PR_IMPLEMENT(void) PR_ClearThreadGCAble()
{
    if (!_pr_initialized) _PR_ImplicitInitialization();
    PR_Lock(_pr_activeLock);
        _PR_MD_CURRENT_THREAD()->flags &= (~_PR_GCABLE_THREAD);
        PR_Unlock(_pr_activeLock);
}

PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thread)
{
    if (!_pr_initialized) _PR_ImplicitInitialization();

    if (_PR_IS_NATIVE_THREAD(thread)) {
    	return (thread->flags & _PR_BOUND_THREAD) ? PR_GLOBAL_BOUND_THREAD :
										PR_GLOBAL_THREAD;
    } else
        return PR_LOCAL_THREAD;
}

PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thread)
{
    return (thread->flags & _PR_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD;
}

PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thread)
{
    return (NULL == thread->term) ? PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD;
}  /* PR_GetThreadState */

deps/mozilla/nsprpub/pr/src/threads/prdump.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

#if defined(WIN95)
/*
** Some local variables report warnings on Win95 because the code paths 
** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
** The pragma suppresses the warning.
** 
*/
#pragma warning(disable : 4101)
#endif

/* XXX use unbuffered nspr stdio */

PRFileDesc *_pr_dumpOut;

PRUint32 _PR_DumpPrintf(PRFileDesc *fd, const char *fmt, ...)
{
    char buf[100];
    PRUint32 nb;
    va_list ap;

    va_start(ap, fmt);
    nb = PR_vsnprintf(buf, sizeof(buf), fmt, ap);
    va_end(ap);
    PR_Write(fd, buf, nb);

    return nb;
}

void _PR_DumpThread(PRFileDesc *fd, PRThread *thread)
{

#ifndef _PR_GLOBAL_THREADS_ONLY
    _PR_DumpPrintf(fd, "%05d[%08p] pri=%2d flags=0x%02x",
                   thread->id, thread, thread->priority, thread->flags);
    switch (thread->state) {
      case _PR_RUNNABLE:
      case _PR_RUNNING:
        break;
      case _PR_LOCK_WAIT:
        _PR_DumpPrintf(fd, " lock=%p", thread->wait.lock);
        break;
      case _PR_COND_WAIT:
        _PR_DumpPrintf(fd, " condvar=%p sleep=%lldms",
                       thread->wait.cvar, thread->sleep);
        break;
      case _PR_SUSPENDED:
        _PR_DumpPrintf(fd, " suspended");
        break;
    }
    PR_Write(fd, "\n", 1);
#endif

    /* Now call dump routine */
    if (thread->dump) {
	thread->dump(fd, thread, thread->dumpArg);
    }
}

static void DumpThreadQueue(PRFileDesc *fd, PRCList *list)
{
#ifndef _PR_GLOBAL_THREADS_ONLY
    PRCList *q;

    q = list->next;
    while (q != list) {
        PRThread *t = _PR_THREAD_PTR(q);
        _PR_DumpThread(fd, t);
        q = q->next;
    }
#endif
}

void _PR_DumpThreads(PRFileDesc *fd)
{
    PRThread *t;
    PRIntn i;

    _PR_DumpPrintf(fd, "Current Thread:\n");
    t = _PR_MD_CURRENT_THREAD();
    _PR_DumpThread(fd, t);

    _PR_DumpPrintf(fd, "Runnable Threads:\n");
    for (i = 0; i < 32; i++) {
        DumpThreadQueue(fd, &_PR_RUNQ(t->cpu)[i]);
    }

    _PR_DumpPrintf(fd, "CondVar timed wait Threads:\n");
    DumpThreadQueue(fd, &_PR_SLEEPQ(t->cpu));

    _PR_DumpPrintf(fd, "CondVar wait Threads:\n");
    DumpThreadQueue(fd, &_PR_PAUSEQ(t->cpu));

    _PR_DumpPrintf(fd, "Suspended Threads:\n");
    DumpThreadQueue(fd, &_PR_SUSPENDQ(t->cpu));
}

PR_IMPLEMENT(void) PR_ShowStatus(void)
{
    PRIntn is;

    if ( _PR_MD_CURRENT_THREAD()
    && !_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) _PR_INTSOFF(is);
    _pr_dumpOut = _pr_stderr;
    _PR_DumpThreads(_pr_dumpOut);
    if ( _PR_MD_CURRENT_THREAD()
    && !_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) _PR_FAST_INTSON(is);
}

PR_IMPLEMENT(void)
PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg)
{
    thread->dump = dump;
    thread->dumpArg = arg;
}

deps/mozilla/nsprpub/pr/src/threads/prmon.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

/************************************************************************/

/*
** Create a new monitor.
*/
PR_IMPLEMENT(PRMonitor*) PR_NewMonitor()
{
    PRMonitor *mon;
	PRCondVar *cvar;
	PRLock *lock;

    mon = PR_NEWZAP(PRMonitor);
    if (mon) {
		lock = PR_NewLock();
	    if (!lock) {
			PR_DELETE(mon);
			return 0;
    	}

	    cvar = PR_NewCondVar(lock);
	    if (!cvar) {
	    	PR_DestroyLock(lock);
			PR_DELETE(mon);
			return 0;
    	}
    	mon->cvar = cvar;
	mon->name = NULL;
    }
    return mon;
}

PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
{
    PRMonitor* mon = PR_NewMonitor();
    if (mon)
        mon->name = name;
    return mon;
}

/*
** Destroy a monitor. There must be no thread waiting on the monitor's
** condition variable. The caller is responsible for guaranteeing that the
** monitor is no longer in use.
*/
PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
{
	PR_DestroyLock(mon->cvar->lock);
    PR_DestroyCondVar(mon->cvar);
    PR_DELETE(mon);
}

/*
** Enter the lock associated with the monitor.
*/
PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
{
    if (mon->cvar->lock->owner == _PR_MD_CURRENT_THREAD()) {
		mon->entryCount++;
    } else {
		PR_Lock(mon->cvar->lock);
		mon->entryCount = 1;
    }
}

/*
** Test and then enter the lock associated with the monitor if it's not
** already entered by some other thread. Return PR_FALSE if some other
** thread owned the lock at the time of the call.
*/
PR_IMPLEMENT(PRBool) PR_TestAndEnterMonitor(PRMonitor *mon)
{
    if (mon->cvar->lock->owner == _PR_MD_CURRENT_THREAD()) {
		mon->entryCount++;
		return PR_TRUE;
    } else {
		if (PR_TestAndLock(mon->cvar->lock)) {
	    	mon->entryCount = 1;
	   	 	return PR_TRUE;
		}
    }
    return PR_FALSE;
}

/*
** Exit the lock associated with the monitor once.
*/
PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
{
    if (mon->cvar->lock->owner != _PR_MD_CURRENT_THREAD()) {
        return PR_FAILURE;
    }
    if (--mon->entryCount == 0) {
		return PR_Unlock(mon->cvar->lock);
    }
    return PR_SUCCESS;
}

/*
** Return the number of times that the current thread has entered the
** lock. Returns zero if the current thread has not entered the lock.
*/
PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
{
    return (mon->cvar->lock->owner == _PR_MD_CURRENT_THREAD()) ?
        mon->entryCount : 0;
}

/*
** If the current thread is in |mon|, this assertion is guaranteed to
** succeed.  Otherwise, the behavior of this function is undefined.
*/
PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
{
    PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(mon->cvar->lock);
}

/*
** Wait for a notify on the condition variable. Sleep for "ticks" amount
** of time (if "tick" is 0 then the sleep is indefinite). While
** the thread is waiting it exits the monitors lock (as if it called
** PR_ExitMonitor as many times as it had called PR_EnterMonitor).  When
** the wait has finished the thread regains control of the monitors lock
** with the same entry count as before the wait began.
**
** The thread waiting on the monitor will be resumed when the monitor is
** notified (assuming the thread is the next in line to receive the
** notify) or when the "ticks" elapses.
**
** Returns PR_FAILURE if the caller has not locked the lock associated
** with the condition variable.
** This routine can return PR_PENDING_INTERRUPT if the waiting thread 
** has been interrupted.
*/
PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks)
{
    PRUintn entryCount;
	PRStatus status;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if (mon->cvar->lock->owner != me) return PR_FAILURE;

    entryCount = mon->entryCount;
    mon->entryCount = 0;

	status = _PR_WaitCondVar(me, mon->cvar, mon->cvar->lock, ticks);

    mon->entryCount = entryCount;

    return status;
}

/*
** Notify the highest priority thread waiting on the condition
** variable. If a thread is waiting on the condition variable (using
** PR_Wait) then it is awakened and begins waiting on the monitor's lock.
*/
PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    if (mon->cvar->lock->owner != me) return PR_FAILURE;
    PR_NotifyCondVar(mon->cvar);
    return PR_SUCCESS;
}

/*
** Notify all of the threads waiting on the condition variable. All of
** threads are notified in turn. The highest priority thread will
** probably acquire the monitor first when the monitor is exited.
*/
PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    if (mon->cvar->lock->owner != me) return PR_FAILURE;
    PR_NotifyAllCondVar(mon->cvar);
    return PR_SUCCESS;
}

/************************************************************************/

PRUint32 _PR_MonitorToString(PRMonitor *mon, char *buf, PRUint32 buflen)
{
    PRUint32 nb;

    if (mon->cvar->lock->owner) {
	nb = PR_snprintf(buf, buflen, "[%p] owner=%d[%p] count=%ld",
			 mon, mon->cvar->lock->owner->id,
			 mon->cvar->lock->owner, mon->entryCount);
    } else {
	nb = PR_snprintf(buf, buflen, "[%p]", mon);
    }
    return nb;
}

deps/mozilla/nsprpub/pr/src/threads/prrwlock.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"

#include <string.h>

#if defined(HPUX) && defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)

#include <pthread.h>
#define HAVE_UNIX98_RWLOCK
#define RWLOCK_T pthread_rwlock_t
#define RWLOCK_INIT(lock) pthread_rwlock_init(lock, NULL)
#define RWLOCK_DESTROY(lock) pthread_rwlock_destroy(lock)
#define RWLOCK_RDLOCK(lock) pthread_rwlock_rdlock(lock)
#define RWLOCK_WRLOCK(lock) pthread_rwlock_wrlock(lock)
#define RWLOCK_UNLOCK(lock) pthread_rwlock_unlock(lock)

#elif defined(SOLARIS) && (defined(_PR_PTHREADS) \
        || defined(_PR_GLOBAL_THREADS_ONLY))

#include <synch.h>
#define HAVE_UI_RWLOCK
#define RWLOCK_T rwlock_t
#define RWLOCK_INIT(lock) rwlock_init(lock, USYNC_THREAD, NULL)
#define RWLOCK_DESTROY(lock) rwlock_destroy(lock)
#define RWLOCK_RDLOCK(lock) rw_rdlock(lock)
#define RWLOCK_WRLOCK(lock) rw_wrlock(lock)
#define RWLOCK_UNLOCK(lock) rw_unlock(lock)

#endif

/*
 * Reader-writer lock
 */
struct PRRWLock {
	char			*rw_name;			/* lock name					*/
	PRUint32		rw_rank;			/* rank of the lock				*/

#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
	RWLOCK_T		rw_lock;
#else
    PRLock			*rw_lock;
	PRInt32			rw_lock_cnt;		/* ==  0, if unlocked			*/
										/* == -1, if write-locked		*/
										/* > 0	, # of read locks		*/
	PRUint32		rw_reader_cnt;		/* number of waiting readers	*/
	PRUint32		rw_writer_cnt;		/* number of waiting writers	*/
	PRCondVar   	*rw_reader_waitq;	/* cvar for readers 			*/
	PRCondVar   	*rw_writer_waitq;	/* cvar for writers				*/
#ifdef DEBUG
    PRThread 		*rw_owner;			/* lock owner for write-lock	*/
#endif
#endif
};

#ifdef DEBUG
#define _PR_RWLOCK_RANK_ORDER_DEBUG	/* enable deadlock detection using
									   rank-order for locks
									*/
#endif

#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG

static PRUintn	pr_thread_rwlock_key;			/* TPD key for lock stack */
static PRUintn	pr_thread_rwlock_alloc_failed;

#define	_PR_RWLOCK_RANK_ORDER_LIMIT	10

typedef struct thread_rwlock_stack {
	PRInt32		trs_index;									/* top of stack */
	PRRWLock	*trs_stack[_PR_RWLOCK_RANK_ORDER_LIMIT];	/* stack of lock
														 	   pointers */

} thread_rwlock_stack;

static void _PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock);
static PRUint32 _PR_GET_THREAD_RWLOCK_RANK(void);
static void _PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock);
static void _PR_RELEASE_LOCK_STACK(void *lock_stack);

#endif

/*
 * Reader/Writer Locks
 */

/*
 * PR_NewRWLock
 *		Create a reader-writer lock, with the given lock rank and lock name
 *	
 */

PR_IMPLEMENT(PRRWLock *)
PR_NewRWLock(PRUint32 lock_rank, const char *lock_name)
{
    PRRWLock *rwlock;
#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
	int err;
#endif

    if (!_pr_initialized) _PR_ImplicitInitialization();

    rwlock = PR_NEWZAP(PRRWLock);
    if (rwlock == NULL)
		return NULL;

	rwlock->rw_rank = lock_rank;
	if (lock_name != NULL) {
		rwlock->rw_name = (char*) PR_Malloc(strlen(lock_name) + 1);
    	if (rwlock->rw_name == NULL) {
			PR_DELETE(rwlock);
			return(NULL);
		}
		strcpy(rwlock->rw_name, lock_name);
	} else {
		rwlock->rw_name = NULL;
	}
	
#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
	err = RWLOCK_INIT(&rwlock->rw_lock);
	if (err != 0) {
		PR_SetError(PR_UNKNOWN_ERROR, err);
		PR_Free(rwlock->rw_name);
		PR_DELETE(rwlock);
		return NULL;
	}
	return rwlock;
#else
	rwlock->rw_lock = PR_NewLock();
    if (rwlock->rw_lock == NULL) {
		goto failed;
	}
	rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock);
    if (rwlock->rw_reader_waitq == NULL) {
		goto failed;
	}
	rwlock->rw_writer_waitq = PR_NewCondVar(rwlock->rw_lock);
    if (rwlock->rw_writer_waitq == NULL) {
		goto failed;
	}
	rwlock->rw_reader_cnt = 0;
	rwlock->rw_writer_cnt = 0;
	rwlock->rw_lock_cnt = 0;
	return rwlock;

failed:
	if (rwlock->rw_reader_waitq != NULL) {
		PR_DestroyCondVar(rwlock->rw_reader_waitq);	
	}
	if (rwlock->rw_lock != NULL) {
		PR_DestroyLock(rwlock->rw_lock);
	}
	PR_Free(rwlock->rw_name);
	PR_DELETE(rwlock);
	return NULL;
#endif
}

/*
** Destroy the given RWLock "lock".
*/
PR_IMPLEMENT(void)
PR_DestroyRWLock(PRRWLock *rwlock)
{
#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
	int err;
	err = RWLOCK_DESTROY(&rwlock->rw_lock);
	PR_ASSERT(err == 0);
#else
	PR_ASSERT(rwlock->rw_reader_cnt == 0);
	PR_DestroyCondVar(rwlock->rw_reader_waitq);	
	PR_DestroyCondVar(rwlock->rw_writer_waitq);	
	PR_DestroyLock(rwlock->rw_lock);
#endif
	if (rwlock->rw_name != NULL)
		PR_Free(rwlock->rw_name);
    PR_DELETE(rwlock);
}

/*
** Read-lock the RWLock.
*/
PR_IMPLEMENT(void)
PR_RWLock_Rlock(PRRWLock *rwlock)
{
#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
int err;
#endif

#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
	/*
	 * assert that rank ordering is not violated; the rank of 'rwlock' should
	 * be equal to or greater than the highest rank of all the locks held by
	 * the thread.
	 */
	PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) || 
					(rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK()));
#endif

#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
	err = RWLOCK_RDLOCK(&rwlock->rw_lock);
	PR_ASSERT(err == 0);
#else
	PR_Lock(rwlock->rw_lock);
	/*
	 * wait if write-locked or if a writer is waiting; preference for writers
	 */
	while ((rwlock->rw_lock_cnt < 0) ||
			(rwlock->rw_writer_cnt > 0)) {
		rwlock->rw_reader_cnt++;
		PR_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT);
		rwlock->rw_reader_cnt--;
	}
	/*
	 * Increment read-lock count
	 */
	rwlock->rw_lock_cnt++;

	PR_Unlock(rwlock->rw_lock);
#endif

#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
	/*
	 * update thread's lock rank
	 */
	_PR_SET_THREAD_RWLOCK_RANK(rwlock);
#endif
}

/*
** Write-lock the RWLock.
*/
PR_IMPLEMENT(void)
PR_RWLock_Wlock(PRRWLock *rwlock)
{
#if defined(DEBUG)
PRThread *me = PR_GetCurrentThread();
#endif
#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
int err;
#endif

#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
	/*
	 * assert that rank ordering is not violated; the rank of 'rwlock' should
	 * be equal to or greater than the highest rank of all the locks held by
	 * the thread.
	 */
	PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) || 
					(rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK()));
#endif

#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
	err = RWLOCK_WRLOCK(&rwlock->rw_lock);
	PR_ASSERT(err == 0);
#else
	PR_Lock(rwlock->rw_lock);
	/*
	 * wait if read locked
	 */
	while (rwlock->rw_lock_cnt != 0) {
		rwlock->rw_writer_cnt++;
		PR_WaitCondVar(rwlock->rw_writer_waitq, PR_INTERVAL_NO_TIMEOUT);
		rwlock->rw_writer_cnt--;
	}
	/*
	 * apply write lock
	 */
	rwlock->rw_lock_cnt--;
	PR_ASSERT(rwlock->rw_lock_cnt == -1);
#ifdef DEBUG
	PR_ASSERT(me != NULL);
	rwlock->rw_owner = me;
#endif
	PR_Unlock(rwlock->rw_lock);
#endif

#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
	/*
	 * update thread's lock rank
	 */
	_PR_SET_THREAD_RWLOCK_RANK(rwlock);
#endif
}

/*
** Unlock the RW lock.
*/
PR_IMPLEMENT(void)
PR_RWLock_Unlock(PRRWLock *rwlock)
{
#if defined(DEBUG)
PRThread *me = PR_GetCurrentThread();
#endif
#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
int err;
#endif

#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
	err = RWLOCK_UNLOCK(&rwlock->rw_lock);
	PR_ASSERT(err == 0);
#else
	PR_Lock(rwlock->rw_lock);
	/*
	 * lock must be read or write-locked
	 */
	PR_ASSERT(rwlock->rw_lock_cnt != 0);
	if (rwlock->rw_lock_cnt > 0) {

		/*
		 * decrement read-lock count
		 */
		rwlock->rw_lock_cnt--;
		if (rwlock->rw_lock_cnt == 0) {
			/*
			 * lock is not read-locked anymore; wakeup a waiting writer
			 */
			if (rwlock->rw_writer_cnt > 0)
				PR_NotifyCondVar(rwlock->rw_writer_waitq);
		}
	} else {
		PR_ASSERT(rwlock->rw_lock_cnt == -1);

		rwlock->rw_lock_cnt = 0;
#ifdef DEBUG
    	PR_ASSERT(rwlock->rw_owner == me);
    	rwlock->rw_owner = NULL;
#endif
		/*
		 * wakeup a writer, if present; preference for writers
		 */
		if (rwlock->rw_writer_cnt > 0)
			PR_NotifyCondVar(rwlock->rw_writer_waitq);
		/*
		 * else, wakeup all readers, if any
		 */
		else if (rwlock->rw_reader_cnt > 0)
			PR_NotifyAllCondVar(rwlock->rw_reader_waitq);
	}
	PR_Unlock(rwlock->rw_lock);
#endif

#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
	/*
	 * update thread's lock rank
	 */
	_PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
#endif
	return;
}

#ifndef _PR_RWLOCK_RANK_ORDER_DEBUG

void _PR_InitRWLocks(void) { }

#else

void _PR_InitRWLocks(void)
{
	/*
	 * allocated thread-private-data index for rwlock list
	 */
	if (PR_NewThreadPrivateIndex(&pr_thread_rwlock_key,
			_PR_RELEASE_LOCK_STACK) == PR_FAILURE) {
		pr_thread_rwlock_alloc_failed = 1;
		return;
	}
}

/*
 * _PR_SET_THREAD_RWLOCK_RANK
 *		Set a thread's lock rank, which is the highest of the ranks of all
 *		the locks held by the thread. Pointers to the locks are added to a
 *		per-thread list, which is anchored off a thread-private data key.
 */

static void
_PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
{
thread_rwlock_stack *lock_stack;
PRStatus rv;

	/*
	 * allocate a lock stack
	 */
	if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL) {
		lock_stack = (thread_rwlock_stack *)
						PR_CALLOC(1 * sizeof(thread_rwlock_stack));
		if (lock_stack) {
			rv = PR_SetThreadPrivate(pr_thread_rwlock_key, lock_stack);
			if (rv == PR_FAILURE) {
				PR_DELETE(lock_stack);
				pr_thread_rwlock_alloc_failed = 1;
				return;
			}
		} else {
			pr_thread_rwlock_alloc_failed = 1;
			return;
		}
	}
	/*
	 * add rwlock to lock stack, if limit is not exceeded
	 */
	if (lock_stack) {
		if (lock_stack->trs_index < _PR_RWLOCK_RANK_ORDER_LIMIT)
			lock_stack->trs_stack[lock_stack->trs_index++] = rwlock;	
	}
}

static void
_PR_RELEASE_LOCK_STACK(void *lock_stack)
{
	PR_ASSERT(lock_stack);
	PR_DELETE(lock_stack);
}

/*
 * _PR_GET_THREAD_RWLOCK_RANK
 *
 *		return thread's lock rank. If thread-private-data for the lock
 *		stack is not allocated, return PR_RWLOCK_RANK_NONE.
 */
	
static PRUint32
_PR_GET_THREAD_RWLOCK_RANK(void)
{
	thread_rwlock_stack *lock_stack;

	if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL)
		return (PR_RWLOCK_RANK_NONE);
	else
		return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
}

/*
 * _PR_UNSET_THREAD_RWLOCK_RANK
 *
 *		remove the rwlock from the lock stack. Since locks may not be
 *		unlocked in a FIFO order, the entire lock stack is searched.
 */
	
static void
_PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
{
	thread_rwlock_stack *lock_stack;
	int new_index = 0, index, done = 0;

	lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key);

	PR_ASSERT(lock_stack != NULL);

	index = lock_stack->trs_index - 1;
	while (index-- >= 0) {
		if ((lock_stack->trs_stack[index] == rwlock) && !done)  {
			/*
			 * reset the slot for rwlock
			 */
			lock_stack->trs_stack[index] = NULL;
			done = 1;
		}
		/*
		 * search for the lowest-numbered empty slot, above which there are
		 * no non-empty slots
		 */
		if ((lock_stack->trs_stack[index] != NULL) && !new_index)
			new_index = index + 1;
		if (done && new_index)
			break;
	}
	/*
	 * set top of stack to highest numbered empty slot
	 */
	lock_stack->trs_index = new_index;

}

#endif 	/* _PR_RWLOCK_RANK_ORDER_DEBUG */

deps/mozilla/nsprpub/pr/src/threads/prsem.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "primpl.h"
#include "obsolete/prsem.h"

/************************************************************************/

/*
** Create a new semaphore.
*/
PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
{
    PRSemaphore *sem;
    PRCondVar *cvar;
    PRLock *lock;

    sem = PR_NEWZAP(PRSemaphore);
    if (sem) {
#ifdef HAVE_CVAR_BUILT_ON_SEM
        _PR_MD_NEW_SEM(&sem->md, value);
#else
        lock = PR_NewLock();
        if (!lock) {
            PR_DELETE(sem);
            return NULL;
    	}

        cvar = PR_NewCondVar(lock);
        if (!cvar) {
            PR_DestroyLock(lock);
            PR_DELETE(sem);
            return NULL;
    	}
    	sem->cvar = cvar;
    	sem->count = value;
#endif
    }
    return sem;
}

/*
** Destroy a semaphore. There must be no thread waiting on the semaphore.
** The caller is responsible for guaranteeing that the semaphore is
** no longer in use.
*/
PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *sem)
{
#ifdef HAVE_CVAR_BUILT_ON_SEM
    _PR_MD_DESTROY_SEM(&sem->md);
#else
    PR_ASSERT(sem->waiters == 0);

    PR_DestroyLock(sem->cvar->lock);
    PR_DestroyCondVar(sem->cvar);
#endif
    PR_DELETE(sem);
}

/*
** Wait on a Semaphore.
** 
** This routine allows a calling thread to wait or proceed depending upon the 
** state of the semahore sem. The thread can proceed only if the counter value 
** of the semaphore sem is currently greater than 0. If the value of semaphore 
** sem is positive, it is decremented by one and the routine returns immediately 
** allowing the calling thread to continue. If the value of semaphore sem is 0, 
** the calling thread blocks awaiting the semaphore to be released by another 
** thread.
** 
** This routine can return PR_PENDING_INTERRUPT if the waiting thread 
** has been interrupted.
*/
PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *sem)
{
	PRStatus status = PR_SUCCESS;

#ifdef HAVE_CVAR_BUILT_ON_SEM
	return _PR_MD_WAIT_SEM(&sem->md);
#else
	PR_Lock(sem->cvar->lock);
	while (sem->count == 0) {
		sem->waiters++;
		status = PR_WaitCondVar(sem->cvar, PR_INTERVAL_NO_TIMEOUT);
		sem->waiters--;
		if (status != PR_SUCCESS)
			break;
	}
	if (status == PR_SUCCESS)
		sem->count--;
	PR_Unlock(sem->cvar->lock);
#endif
	
	return (status);
}

/*
** This routine increments the counter value of the semaphore. If other threads 
** are blocked for the semaphore, then the scheduler will determine which ONE 
** thread will be unblocked.
*/
PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *sem)
{
#ifdef HAVE_CVAR_BUILT_ON_SEM
	_PR_MD_POST_SEM(&sem->md);
#else
	PR_Lock(sem->cvar->lock);
	if (sem->waiters)
		PR_NotifyCondVar(sem->cvar);
	sem->count++;
	PR_Unlock(sem->cvar->lock);
#endif
}

#if DEBUG
/*
** Returns the value of the semaphore referenced by sem without affecting
** the state of the semaphore.  The value represents the semaphore vaule
** at the time of the call, but may not be the actual value when the
** caller inspects it. (FOR DEBUGGING ONLY)
*/
PR_IMPLEMENT(PRUintn) PR_GetValueSem(PRSemaphore *sem)
{
	PRUintn rv;

#ifdef HAVE_CVAR_BUILT_ON_SEM
	rv = _PR_MD_GET_VALUE_SEM(&sem->md);
#else
	PR_Lock(sem->cvar->lock);
	rv = sem->count;
	PR_Unlock(sem->cvar->lock);
#endif
	
	return rv;
}
#endif

deps/mozilla/nsprpub/pr/src/threads/prtpd.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
** Thread Private Data
**
** There is an aribitrary limit on the number of keys that will be allocated
** by the runtime. It's largish, so it is intended to be a sanity check, not
** an impediment.
**
** There is a counter, initialized to zero and incremented every time a
** client asks for a new key, that holds the high water mark for keys. All
** threads logically have the same high water mark and are permitted to
** ask for TPD up to that key value.
**
** The vector to hold the TPD are allocated when PR_SetThreadPrivate() is
** called. The size of the vector will be some value greater than or equal
** to the current high water mark. Each thread has its own TPD length and
** vector.
**
** Threads that get private data for keys they have not set (or perhaps
** don't even exist for that thread) get a NULL return. If the key is
** beyond the high water mark, an error will be returned.
*/

/*
** As of this time, BeOS has its own TPD implementation.  Integrating
** this standard one is a TODO for anyone with a bit of spare time on
** their hand.  For now, we just #ifdef out this whole file and use
** the routines in pr/src/btthreads/
*/

#ifndef XP_BEOS

#include "primpl.h"

#include <string.h>

#if defined(WIN95)
/*
** Some local variables report warnings on Win95 because the code paths 
** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
** The pragma suppresses the warning.
** 
*/
#pragma warning(disable : 4101)
#endif

#define _PR_TPD_LIMIT 128               /* arbitary limit on the TPD slots */
static PRInt32 _pr_tpd_length = 0;      /* current length of destructor vector */
static PRInt32 _pr_tpd_highwater = 0;   /* next TPD key to be assigned */
static PRThreadPrivateDTOR *_pr_tpd_destructors = NULL;
                                        /* the destructors are associated with
                                            the keys, therefore asserting that
                                            the TPD key depicts the data's 'type' */

/*
** Initialize the thread private data manipulation
*/
void _PR_InitTPD(void)
{
    _pr_tpd_destructors = (PRThreadPrivateDTOR*)
        PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*));
    PR_ASSERT(NULL != _pr_tpd_destructors);
    _pr_tpd_length = _PR_TPD_LIMIT;
}

/*
** Clean up the thread private data manipulation
*/
void _PR_CleanupTPD(void)
{
}  /* _PR_CleanupTPD */

/*
** This routine returns a new index for per-thread-private data table. 
** The index is visible to all threads within a process. This index can 
** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines 
** to save and retrieve data associated with the index for a thread.
**
** The index independently maintains specific values for each binding thread. 
** A thread can only get access to its own thread-specific-data.
**
** Upon a new index return the value associated with the index for all threads
** is NULL, and upon thread creation the value associated with all indices for 
** that thread is NULL. 
**
**     "dtor" is the destructor function to invoke when the private
**       data is set or destroyed
**
** Returns PR_FAILURE if the total number of indices will exceed the maximun 
** allowed.
*/

PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex(
    PRUintn *newIndex, PRThreadPrivateDTOR dtor)
{
    PRStatus rv;
    PRInt32 index;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    PR_ASSERT(NULL != newIndex);
    PR_ASSERT(NULL != _pr_tpd_destructors);

    index = PR_ATOMIC_INCREMENT(&_pr_tpd_highwater) - 1;  /* allocate index */
    if (_PR_TPD_LIMIT <= index)
    {
        PR_SetError(PR_TPD_RANGE_ERROR, 0);
        rv = PR_FAILURE;  /* that's just wrong */
    }
    else
    {
        _pr_tpd_destructors[index] = dtor;  /* record destructor @index */
        *newIndex = (PRUintn)index;  /* copy into client's location */
        rv = PR_SUCCESS;  /* that's okay */
    }

    return rv;
}

/*
** Define some per-thread-private data.
**     "index" is an index into the per-thread private data table
**     "priv" is the per-thread-private data 
**
** If the per-thread private data table has a previously registered
** destructor function and a non-NULL per-thread-private data value,
** the destructor function is invoked.
**
** This can return PR_FAILURE if index is invalid (ie., beyond the current
** high water mark) or memory is insufficient to allocate an exanded vector.
*/

PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
{
    PRThread *self = PR_GetCurrentThread();

    /*
    ** The index being set might not have a sufficient vector in this
    ** thread. But if the index has been allocated, it's okay to go
    ** ahead and extend this one now.
    */
    if ((index >= _PR_TPD_LIMIT) || (index >= _pr_tpd_highwater))
    {
        PR_SetError(PR_TPD_RANGE_ERROR, 0);
        return PR_FAILURE;
    }

    PR_ASSERT(((NULL == self->privateData) && (0 == self->tpdLength))
        || ((NULL != self->privateData) && (0 != self->tpdLength)));

    if ((NULL == self->privateData) || (self->tpdLength <= index))
    {
        void *extension = PR_CALLOC(_pr_tpd_length * sizeof(void*));
        if (NULL == extension)
        {
            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
            return PR_FAILURE;
        }
        if (self->privateData) {
            (void)memcpy(
                extension, self->privateData,
                self->tpdLength * sizeof(void*));
            PR_DELETE(self->privateData);
        }
        self->tpdLength = _pr_tpd_length;
        self->privateData = (void**)extension;
    }
    /*
    ** There wasn't much chance of having to call the destructor
    ** unless the slot already existed.
    */
    else if (self->privateData[index] && _pr_tpd_destructors[index])
    {
        void *data = self->privateData[index];
        self->privateData[index] = NULL;
        (*_pr_tpd_destructors[index])(data);
    }

    PR_ASSERT(index < self->tpdLength);
    self->privateData[index] = priv;

    return PR_SUCCESS;
}

/*
** Recover the per-thread-private data for the current thread. "index" is
** the index into the per-thread private data table. 
**
** The returned value may be NULL which is indistinguishable from an error 
** condition.
**
*/

PR_IMPLEMENT(void*) PR_GetThreadPrivate(PRUintn index)
{
    PRThread *self = PR_GetCurrentThread();
    void *tpd = ((NULL == self->privateData) || (index >= self->tpdLength)) ?
        NULL : self->privateData[index];

    return tpd;
}

/*
** Destroy the thread's private data, if any exists. This is called at
** thread termination time only. There should be no threading issues
** since this is being called by the thread itself.
*/
void _PR_DestroyThreadPrivate(PRThread* self)
{
#define _PR_TPD_DESTRUCTOR_ITERATIONS 4

    if (NULL != self->privateData)  /* we have some */
    {
        PRBool clean;
        PRUint32 index;
        PRInt32 passes = _PR_TPD_DESTRUCTOR_ITERATIONS;
        PR_ASSERT(0 != self->tpdLength);
        do
        {
            clean = PR_TRUE;
            for (index = 0; index < self->tpdLength; ++index)
            {
                void *priv = self->privateData[index];  /* extract */
                if (NULL != priv)  /* we have data at this index */
                {
                    if (NULL != _pr_tpd_destructors[index])
                    {
                        self->privateData[index] = NULL;  /* precondition */
                        (*_pr_tpd_destructors[index])(priv);  /* destroy */
                        clean = PR_FALSE;  /* unknown side effects */
                    }
                }
            }
        } while ((--passes > 0) && !clean);  /* limit # of passes */
        /*
        ** We give up after a fixed number of passes. Any non-NULL
        ** thread-private data value with a registered destructor
        ** function is not destroyed.
        */
        memset(self->privateData, 0, self->tpdLength * sizeof(void*));
    }
}  /* _PR_DestroyThreadPrivate */

#endif /* !XP_BEOS */

deps/mozilla/nsprpub/pr/tests/README.TXT

File: pr/tests/readme

This document describes the test cases in the NSPR directory
pr/tests.

=====================================================================
There is a sub-directory here:

dll
	sources for the .dll(.so) used by test dlltest.c

=====================================================================
The individual files are described here.

The script 'runtests.ksh' enumerates and runs test cases that are
expected to run on all platforms.


accept.c
	Tests PR_Accept() and related socket functions.

acceptread.c
	Tests PR_AcceptRead()

alarm.c
	Tests alarm functions declared in obsolete/pralarm.h.
	The alarm functions are obsolete, so is this test.

atomic.c
	Tests Atomic operations defined in pratom.h

attach.c
	Test PR_AttachThread()
	Note: This is an NSPR private function.

bigfile.c
	Test 64bit file offset functions declared in prio.h

bug1test.c
	Demonstrates a bug on NT.

cleanup.c
	Tests PR_Cleanup() declared in prinit.h

cltsrv.c
	Tests many socket functions.

concur.c
	Tests threading functions and concurrent operations.

cvar.c
	Tests condition variables.

cvar2.c
	Tests condition variables. A rather abusive test.

dbmalloc.c
	Obsolete. Originally for testing debug builds of NSPR's malloc.

dbmalloc1.c
	Obsolete. Originally for testing debug builds of NSPR's malloc.

dceemu.c
	Tests special functions for DCE emulation.

depend.c
	Obsoltet. Tests early spec for library dependency.

dlltest.c
	Tests dynamic library functions. Used with dll/my.c

dtoa.c
	Tests conversions of double to string.

exit.c
	Tests PR_ProcessExit() declared in prinit.h

fileio.c
	Tests NSPR semaphores a bit of file i/o and threading
	functions.

foreign.c
	Test auto-attach of a thread created by something other than
	NSPR.

forktest.c
	Limited use. Tests unix fork() and related functions.

fsync.c
	Tests use of PR_Sync() declared in prio.h

getproto.c
	Tests socket functions PR_GetProtoByName(), etc.

i2l.c
	Tests LongLong functions for converting 32bit integer to 64bit
	integer.

initclk.c
	Tests timing on minimal use of condition variable

inrval.c
	Tests interval timing functions.

instrumt.c
	Tests instrumentation functions. prcountr.h prtrace.h

intrupt.c
	Tests PR_Interrupt()

ioconthr.c
	Tests i/o continuation mechanism in pthreads.

io_timeout.c
	Test socket i/o timeouts.

io_timeoutk.c
	Obsolete. Subsumed in io_timeout.c

io_timeoutu.c
	Obsolete. Subsumed in io_timeout.c

ipv6.c
	Tests IPv6. IPv6 is not used by NSPR clients.

join.c
	Tests PR_JoinThread()

joinkk.c
	Tests PR_JoinThread()

joinku.c
	Tests PR_JoinThread()

joinuk.c
	Tests PR_JoinThread()

joinuu.c
	Tests PR_JoinThread()

layer.c
	Tests layered I/O.

lazyinit.c
	Tests implicit initialization.

lltest.c
	Tests LongLong (64bit integer) arithmentic and conversions.

lock.c
	Tests PR_Lock() in heavily threaded environment.

lockfile.c
	Test PR_Lockfile().

logger.c
	Tests PR_LOG()

makefile
	The makefile that builds all the tests

many_cv.c
	Tests aquiring a large number of condition variables.

multiwait.c
	???

nbconn.c
	Test non-blocking connect.

nblayer.c
	Tests NSPR's layered I/O capability.

nonblock.c
	Tests operations on non-blocking socket.

op_2long.c
	Tests PR_Open() where filename is too long.

op_filnf.c
	Tests PR_Open() where filename is NotFound.

op_filok.c
	Tests PR_Open() where filename is accessable.

op_noacc.c
	Tests PR_Open() where file permissions are wrong.
	Limited use. Windows has no concept of Unix style file permissions.

op_nofil.c
	Tests PR_Open() where filename does not exist.

parent.c
	Test parent/child process capability

perf.c
	Tests and measures context switch times for various thread
	syncronization functions.

pipeping.c
	Tests inter-process pipes. Run with pipepong.c

pipepong.c
	Tests inter-process pipes. Run with pipeping.c

pipeself.c
	Tests inter-thread pipes.

pollable.c
	Tests pollable events. prio.h

poll_er.c
	Tests PR_Poll() where an error is expected.

poll_nm.c
	Tests PR_Poll() where normal operation is expected.

poll_to.c
	Tests PR_Poll() where timeout is expected.

prftest.c
	Tests printf-like formatting.

prftest1.c
	Obsolete. Subsumed in prftest.c

prftest2.c
	Obsolete. Subsumed in prftest.c

priotest.c
	Limited use. Tests NSPR thread dispatching priority.

provider.c

prpoll.c
	Tests PR_Poll().

prselect.c
	Obsolete. PR_Select() is obsolete.

prttools.h
	Unused file.

ranfile.c
	Tests random file access.

readme
	This file.

runtests.ksh
	A korn shell script that runs a set of tests that should run
	on any of the NSPR supported platforms.

runtests.pl
	A perl script to run the test cases. This srcipt runs tests
	common to all platforms and runs tests applicable to specific
	platforms. Uses file runtests.txt to control execution.

runtests.txt
	Control file for perl script: runtests.pl

rwlocktest.c
	Tests Reader/Writer lock

selct_er.c
	Obsolete. PR_Select() is obsolete.

selct_nm.c
	Obsolete. PR_Select() is obsolete.

selct_to.c
	Obsolete. PR_Select() is obsolete.

select2.c
	Obsolete. PR_Select() is obsolete.

sel_spd.c
	Obsolete. PR_Select() is obsolete.

sem.c
	Obsolete. Semaphores are not supported.

server_test.c
	Tests sockets by simulating a server in loopback mode.
	Makes its own client threads.

servr_kk.c
	Tests client/server sockets, threads using system threads.

servr_ku.c
	Tests client/server sockets, threads using system and user threads.

servr_uk.c
	Tests client/server sockets, threads using system and user threads.

servr_uu.c
	Tests client/server sockets, threads user threads.

short_thread.c
	Tests short-running threads. Useful for testing for race conditions.

sigpipe.c
	Tests NSPR's SIGPIPE handler. Unix only.

sleep.c
	Limited use. Tests sleep capability of platform.

socket.c
	Tests many socket functions.

sockopt.c
	Tests setting and getting socket options.

sprintf.c
	Tests sprintf.

sproc_ch.c
	Obsolete. Tests IRIX sproc-based threads.

sproc_p.c
	Obsolete. Tests IRIX sproc-based threads.

stack.c
	Test atomic stack operations.

stat.c
	Tests performance of getfileinfo() vs. stat()

stdio.c
	Tests NSPR's handling of stdin, stdout, stderr.

strod.c
	Tests formatting of double precision floating point.

suspend.c
	Private interfaces PR_SuspendAll(), PR_ResumeAll(), etc.

switch.c
	Tests thread switching

system.c
	Tests PR_GetSystemInfo()

testbit.c
	Tests bit arrays.

testfile.c
	Tests many file I/O functions.

threads.c
	Tests thread caching.

thruput.c
	Tests socket thruput. Must be run by hand as client/server.
	Does not self terminate.

time.c
	Incomplete. Limited use.

timemac.c
	Test time and date functions. Originally for Mac.

timetest.c
	Tests time conversion over a wide range of dates.

tmoacc.c
	Server to tmocon.c and writev.c
	Do not run it by itself.

tmocon.c
	Client thread to tmoacc.c

tpd.c
	Tests thread private data.

udpsrv.c
	Tests UDP socket functions.

ut_ttools.h
	unused file.

version.c
	Extract and print library version data.

vercheck.c
	Test PR_VersionCheck().

writev.c
	Tests gather-write on a socket. Requires tmoacc.c

xnotify.c
	Tests cached monitors.

yield.c
	Limited use

y2k.c
	Test to verify NSPR's date functions as Y2K compliant.

dll\Makefile
	makefile for mygetval.c, mysetval.c

dll\mygetval.c
	Dynamic library test. See also dlltest.c

dll\mysetval.c
	Dynamic library test. See also dlltest.c

deps/mozilla/nsprpub/pr/tests/acceptread.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <prio.h>
#include <prprf.h>
#include <prinit.h>
#include <prnetdb.h>
#include <prinrval.h>
#include <prthread.h>

#include <plerror.h>

#include <stdlib.h>

#define DEFAULT_PORT 12273
#define GET "GET / HTTP/1.0\n\n"
static PRFileDesc *std_out, *err_out;
static PRIntervalTime write_dally, accept_timeout;

static PRStatus PrintAddress(const PRNetAddr* address)
{
    char buffer[100];
    PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
    if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString");
    else PR_fprintf(
        std_out, "Accepted connection from (0x%p)%s:%d\n",
        address, buffer, address->inet.port);
    return rv;
}  /* PrintAddress */

static void ConnectingThread(void *arg)
{
    PRInt32 nbytes;
#ifdef SYMBIAN
    char buf[256];
#else
    char buf[1024];
#endif
    PRFileDesc *sock;
    PRNetAddr peer_addr, *addr;

    addr = (PRNetAddr*)arg;

    sock = PR_NewTCPSocket();
    if (sock == NULL)
    {
        PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
        PR_ProcessExit(1);
    }

    if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_Connect (client) failed");
        PR_ProcessExit(1);
    }
    if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
        PR_ProcessExit(1);
    }

    /*
    ** Then wait between the connection coming up and sending the expected
    ** data. At some point in time, the server should fail due to a timeou
    ** on the AcceptRead() operation, which according to the document is
    ** only due to the read() portion.
    */
    PR_Sleep(write_dally);

    nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
    if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");

    nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
    if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
    else
    {
        PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
        buf[sizeof(buf) - 1] = '\0';
        PR_fprintf(std_out, "%s\n", buf);
    }

    if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
        PL_FPrintError(err_out, "PR_Shutdown (client) failed");

    if (PR_FAILURE == PR_Close(sock))
        PL_FPrintError(err_out, "PR_Close (client) failed");

    return;
}  /* ConnectingThread */

#define BUF_SIZE 117
static void AcceptingThread(void *arg)
{
    PRStatus rv;
    PRInt32 bytes;
    PRSize buf_size = BUF_SIZE;
    PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
    PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
    PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
    PRSocketOptionData sock_opt;

    if (NULL == listen_sock)
    {
        PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
        PR_ProcessExit(1);        
    }
    sock_opt.option = PR_SockOpt_Reuseaddr;
    sock_opt.value.reuse_addr = PR_TRUE;
    rv = PR_SetSocketOption(listen_sock, &sock_opt);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
        PR_ProcessExit(1);        
    }
    rv = PR_Bind(listen_sock, listen_addr);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_Bind (server) failed");
        PR_ProcessExit(1);        
    }
    rv = PR_Listen(listen_sock, 10);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_Listen (server) failed");
        PR_ProcessExit(1);        
    }
    bytes = PR_AcceptRead(
        listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);

    if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
    else
    {
        PrintAddress(accept_addr);
        PR_fprintf(
            std_out, "(Server) read [0x%p..0x%p) %s\n",
            buf, &buf[BUF_SIZE], buf);
        bytes = PR_Write(accept_sock, buf, bytes);
        rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
        if (PR_FAILURE == rv)
            PL_FPrintError(err_out, "PR_Shutdown (server) failed");
    }

    if (-1 != bytes)
    {
        rv = PR_Close(accept_sock);
        if (PR_FAILURE == rv)
            PL_FPrintError(err_out, "PR_Close (server) failed");
    }

    rv = PR_Close(listen_sock);
    if (PR_FAILURE == rv)
        PL_FPrintError(err_out, "PR_Close (server) failed");
}  /* AcceptingThread */

int main(int argc, char **argv)
{
    PRHostEnt he;
    PRStatus status;
    PRIntn next_index;
    PRUint16 port_number;
    char netdb_buf[PR_NETDB_BUF_SIZE];
    PRNetAddr client_addr, server_addr;
    PRThread *client_thread, *server_thread;
    PRIntervalTime delta = PR_MillisecondsToInterval(500);

    err_out = PR_STDERR;
    std_out = PR_STDOUT;
    accept_timeout = PR_SecondsToInterval(2);

    if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
    else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);

    status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
    if (PR_SUCCESS != status)
    {
        PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
        PR_ProcessExit(1);
    }
    if (argc < 3)
    {
        status = PR_InitializeNetAddr(
            PR_IpAddrLoopback, port_number, &client_addr);
        if (PR_SUCCESS != status)
        {
            PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
            PR_ProcessExit(1);
        }
    }
    else
    {
        status = PR_GetHostByName(
            argv[1], netdb_buf, sizeof(netdb_buf), &he);
        if (status == PR_FAILURE)
        {
            PL_FPrintError(err_out, "PR_GetHostByName failed");
            PR_ProcessExit(1);
        }
        next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
        if (next_index == -1)
        {
            PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
            PR_ProcessExit(1);
        }
    }

    for (
        write_dally = 0;
        write_dally < accept_timeout + (2 * delta);
        write_dally += delta)
    {
        PR_fprintf(
            std_out, "Testing w/ write_dally = %d msec\n",
            PR_IntervalToMilliseconds(write_dally));
        server_thread = PR_CreateThread(
            PR_USER_THREAD, AcceptingThread, &server_addr,
            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (server_thread == NULL)
        {
            PL_FPrintError(err_out, "PR_CreateThread (server) failed");
            PR_ProcessExit(1);
        }

        PR_Sleep(delta);  /* let the server pot thicken */

        client_thread = PR_CreateThread(
            PR_USER_THREAD, ConnectingThread, &client_addr,
            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (client_thread == NULL)
        {
            PL_FPrintError(err_out, "PR_CreateThread (client) failed");
            PR_ProcessExit(1);
        }

        if (PR_JoinThread(client_thread) == PR_FAILURE)
            PL_FPrintError(err_out, "PR_JoinThread (client) failed");

        if (PR_JoinThread(server_thread) == PR_FAILURE)
            PL_FPrintError(err_out, "PR_JoinThread (server) failed");
    }

    return 0;
}

deps/mozilla/nsprpub/pr/tests/acceptreademu.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
 * This test is the same as acceptread.c except that it uses the
 * emulated acceptread method instead of the regular acceptread.
 */

#include <prio.h>
#include <prprf.h>
#include <prinit.h>
#include <prnetdb.h>
#include <prinrval.h>
#include <prthread.h>
#include <pprio.h>

#include <plerror.h>

#include <stdlib.h>

#define DEFAULT_PORT 12273
#define GET "GET / HTTP/1.0\n\n"
static PRFileDesc *std_out, *err_out;
static PRIntervalTime write_dally, accept_timeout;
static PRDescIdentity emu_layer_ident;
static PRIOMethods emu_layer_methods;

/* the acceptread method in emu_layer_methods */
static PRInt32 PR_CALLBACK emu_AcceptRead(PRFileDesc *sd, PRFileDesc **nd,
    PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout)
{
    return PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
}

static PRStatus PrintAddress(const PRNetAddr* address)
{
    char buffer[100];
    PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
    if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString");
    else PR_fprintf(
        std_out, "Accepted connection from (0x%p)%s:%d\n",
        address, buffer, address->inet.port);
    return rv;
}  /* PrintAddress */

static void ConnectingThread(void *arg)
{
    PRInt32 nbytes;
#ifdef SYMBIAN
    char buf[256];
#else
    char buf[1024];
#endif
    PRFileDesc *sock;
    PRNetAddr peer_addr, *addr;

    addr = (PRNetAddr*)arg;

    sock = PR_NewTCPSocket();
    if (sock == NULL)
    {
        PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
        PR_ProcessExit(1);
    }

    if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_Connect (client) failed");
        PR_ProcessExit(1);
    }
    if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
        PR_ProcessExit(1);
    }

    /*
    ** Then wait between the connection coming up and sending the expected
    ** data. At some point in time, the server should fail due to a timeou
    ** on the AcceptRead() operation, which according to the document is
    ** only due to the read() portion.
    */
    PR_Sleep(write_dally);

    nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
    if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");

    nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
    if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
    else
    {
        PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
        buf[sizeof(buf) - 1] = '\0';
        PR_fprintf(std_out, "%s\n", buf);
    }

    if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
        PL_FPrintError(err_out, "PR_Shutdown (client) failed");

    if (PR_FAILURE == PR_Close(sock))
        PL_FPrintError(err_out, "PR_Close (client) failed");

    return;
}  /* ConnectingThread */

#define BUF_SIZE 117
static void AcceptingThread(void *arg)
{
    PRStatus rv;
    PRInt32 bytes;
    PRSize buf_size = BUF_SIZE;
    PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
    PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
    PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
    PRFileDesc *layer;
    PRSocketOptionData sock_opt;

    if (NULL == listen_sock)
    {
        PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
        PR_ProcessExit(1);        
    }
    layer = PR_CreateIOLayerStub(emu_layer_ident, &emu_layer_methods);
    if (NULL == layer)
    {
        PL_FPrintError(err_out, "PR_CreateIOLayerStub (server) failed");
        PR_ProcessExit(1);        
    }
    if (PR_PushIOLayer(listen_sock, PR_TOP_IO_LAYER, layer) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_PushIOLayer (server) failed");
        PR_ProcessExit(1);        
    }
    sock_opt.option = PR_SockOpt_Reuseaddr;
    sock_opt.value.reuse_addr = PR_TRUE;
    rv = PR_SetSocketOption(listen_sock, &sock_opt);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
        PR_ProcessExit(1);        
    }
    rv = PR_Bind(listen_sock, listen_addr);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_Bind (server) failed");
        PR_ProcessExit(1);        
    }
    rv = PR_Listen(listen_sock, 10);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_Listen (server) failed");
        PR_ProcessExit(1);        
    }
    bytes = PR_AcceptRead(
        listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);

    if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
    else
    {
        PrintAddress(accept_addr);
        PR_fprintf(
            std_out, "(Server) read [0x%p..0x%p) %s\n",
            buf, &buf[BUF_SIZE], buf);
        bytes = PR_Write(accept_sock, buf, bytes);
        rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
        if (PR_FAILURE == rv)
            PL_FPrintError(err_out, "PR_Shutdown (server) failed");
    }

    if (-1 != bytes)
    {
        rv = PR_Close(accept_sock);
        if (PR_FAILURE == rv)
            PL_FPrintError(err_out, "PR_Close (server) failed");
    }

    rv = PR_Close(listen_sock);
    if (PR_FAILURE == rv)
        PL_FPrintError(err_out, "PR_Close (server) failed");
}  /* AcceptingThread */

int main(int argc, char **argv)
{
    PRHostEnt he;
    PRStatus status;
    PRIntn next_index;
    PRUint16 port_number;
    char netdb_buf[PR_NETDB_BUF_SIZE];
    PRNetAddr client_addr, server_addr;
    PRThread *client_thread, *server_thread;
    PRIntervalTime delta = PR_MillisecondsToInterval(500);

    err_out = PR_STDERR;
    std_out = PR_STDOUT;
    accept_timeout = PR_SecondsToInterval(2);
    emu_layer_ident = PR_GetUniqueIdentity("Emulated AcceptRead");
    emu_layer_methods = *PR_GetDefaultIOMethods();
    emu_layer_methods.acceptread = emu_AcceptRead;

    if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
    else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);

    status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
    if (PR_SUCCESS != status)
    {
        PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
        PR_ProcessExit(1);
    }
    if (argc < 3)
    {
        status = PR_InitializeNetAddr(
            PR_IpAddrLoopback, port_number, &client_addr);
        if (PR_SUCCESS != status)
        {
            PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
            PR_ProcessExit(1);
        }
    }
    else
    {
        status = PR_GetHostByName(
            argv[1], netdb_buf, sizeof(netdb_buf), &he);
        if (status == PR_FAILURE)
        {
            PL_FPrintError(err_out, "PR_GetHostByName failed");
            PR_ProcessExit(1);
        }
        next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
        if (next_index == -1)
        {
            PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
            PR_ProcessExit(1);
        }
    }

    for (
        write_dally = 0;
        write_dally < accept_timeout + (2 * delta);
        write_dally += delta)
    {
        PR_fprintf(
            std_out, "Testing w/ write_dally = %d msec\n",
            PR_IntervalToMilliseconds(write_dally));
        server_thread = PR_CreateThread(
            PR_USER_THREAD, AcceptingThread, &server_addr,
            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (server_thread == NULL)
        {
            PL_FPrintError(err_out, "PR_CreateThread (server) failed");
            PR_ProcessExit(1);
        }

        PR_Sleep(delta);  /* let the server pot thicken */

        client_thread = PR_CreateThread(
            PR_USER_THREAD, ConnectingThread, &client_addr,
            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (client_thread == NULL)
        {
            PL_FPrintError(err_out, "PR_CreateThread (client) failed");
            PR_ProcessExit(1);
        }

        if (PR_JoinThread(client_thread) == PR_FAILURE)
            PL_FPrintError(err_out, "PR_JoinThread (client) failed");

        if (PR_JoinThread(server_thread) == PR_FAILURE)
            PL_FPrintError(err_out, "PR_JoinThread (server) failed");
    }

    return 0;
}

deps/mozilla/nsprpub/pr/tests/short_thread.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <stdio.h>
#include "nspr.h"
#include "plgetopt.h"

/*
 * Create a thread that exits right away; useful for testing race conditions in thread
 * creation
 */

int _debug_on = 0;
#define DPRINTF(arg) if (_debug_on) printf arg

static void housecleaning(void *cur_time);

int main (int argc, char **argv)
{
	static PRIntervalTime thread_start_time;
	static PRThread *housekeeping_tid = NULL;
	PLOptStatus os;
	PLOptState *opt = PL_CreateOptState(argc, argv, "d");

	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
	{
		if (PL_OPT_BAD == os) continue;
		switch (opt->option)
		{
			case 'd':  /* debug mode */
				_debug_on = 1;
				break;
			default:
				break;
		}
	}
	PL_DestroyOptState(opt);

	if (( housekeeping_tid = 
		PR_CreateThread (PR_USER_THREAD, housecleaning,  (void*)&thread_start_time,
						 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0)) 
																		== NULL ) {
		fprintf(stderr,
			"simple_test: Error - PR_CreateThread failed: (%ld, %ld)\n",
									  PR_GetError(), PR_GetOSError());
		exit( 1 );
	}
	PR_Cleanup();
	return(0);
}

static void
housecleaning (void *cur_time) 
{
  DPRINTF(("Child Thread exiting\n"));
}

deps/mozilla/nsprpub/pr/tests/threads.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Netscape Portable Runtime (NSPR).
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "nspr.h"
#include "prinrval.h"
#include "plgetopt.h"
#include "pprthred.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

PRMonitor *mon;
PRInt32 count, iterations, alive;

PRBool debug_mode = PR_FALSE, passed = PR_TRUE;

void 
PR_CALLBACK
ReallyDumbThread(void *arg)
{
    return;
}

void
PR_CALLBACK
DumbThread(void *arg)
{
    PRInt32 tmp = (PRInt32)arg;
    PRThreadScope scope = (PRThreadScope)tmp;
    PRThread *thr;

    thr = PR_CreateThread(PR_USER_THREAD,
                          ReallyDumbThread,
                          NULL,
                          PR_PRIORITY_NORMAL,
                          scope,
                          PR_JOINABLE_THREAD,
                          0);

    if (!thr) {
        if (debug_mode) {
            printf("Could not create really dumb thread (%d, %d)!\n",
                    PR_GetError(), PR_GetOSError());
        }
        passed = PR_FALSE;
    } else {
        PR_JoinThread(thr);
    }
    PR_EnterMonitor(mon);
    alive--;
    PR_Notify(mon);
    PR_ExitMonitor(mon);
}

static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2)
{
    PRThread *thr;
    int n;

    alive = 0;
    mon = PR_NewMonitor();

    alive = count;
    for (n=0; n<count; n++) {
        thr = PR_CreateThread(PR_USER_THREAD,
                              DumbThread, 
                              (void *)scope2, 
                              PR_PRIORITY_NORMAL,
                              scope1,
                              PR_UNJOINABLE_THREAD,
                              0);
        if (!thr) {
            if (debug_mode) {
                printf("Could not create dumb thread (%d, %d)!\n",
                        PR_GetError(), PR_GetOSError());
            }
            passed = PR_FALSE;
            alive--;
        }
         
        PR_Sleep(0);
    }

    /* Wait for all threads to exit */
    PR_EnterMonitor(mon);
    while (alive) {
        PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
    }

    PR_ExitMonitor(mon);
	PR_DestroyMonitor(mon);
}

static void CreateThreadsUU(void)
{
    CreateThreads(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
}

static void CreateThreadsUK(void)
{
    CreateThreads(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
}

static void CreateThreadsKU(void)
{
    CreateThreads(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
}

static void CreateThreadsKK(void)
{
    CreateThreads(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
}

/************************************************************************/

static void Measure(void (*func)(void), const char *msg)
{
    PRIntervalTime start, stop;
    double d;

    start = PR_IntervalNow();
    (*func)();
    stop = PR_IntervalNow();

    if (debug_mode)
    {
        d = (double)PR_IntervalToMicroseconds(stop - start);
        printf("%40s: %6.2f usec\n", msg, d / count);
    }
}

int main(int argc, char **argv)
{
    int index;

    PR_STDIO_INIT();
    PR_Init(PR_USER_THREAD, PR_PRIORITY_HIGH, 0);
    
    {
    	PLOptStatus os;
    	PLOptState *opt = PL_CreateOptState(argc, argv, "dc:i:");
    	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
        {
    		if (PL_OPT_BAD == os) continue;
            switch (opt->option)
            {
            case 'd':  /* debug mode */
    			debug_mode = PR_TRUE;
                break;
            case 'c':  /* loop counter */
    			count = atoi(opt->value);
                break;
            case 'i':  /* loop counter */
    			iterations = atoi(opt->value);
                break;
             default:
                break;
            }
        }
    	PL_DestroyOptState(opt);
    }

    if (0 == count) count = 50;
    if (0 == iterations) iterations = 10;

    if (debug_mode)
    {
    printf("\
** Tests lots of thread creations.  \n\
** Create %ld native threads %ld times. \n\
** Create %ld user threads %ld times \n", iterations,count,iterations,count);
    }

    for (index=0; index<iterations; index++) {
        Measure(CreateThreadsUU, "Create user/user threads");
        Measure(CreateThreadsUK, "Create user/native threads");
        Measure(CreateThreadsKU, "Create native/user threads");
        Measure(CreateThreadsKK, "Create native/native threads");
    }

    if (debug_mode) printf("\nNow switch to recycling threads \n\n");
    PR_SetThreadRecycleMode(1);

    for (index=0; index<iterations; index++) {
        Measure(CreateThreadsUU, "Create user/user threads");
        Measure(CreateThreadsUK, "Create user/native threads");
        Measure(CreateThreadsKU, "Create native/user threads");
        Measure(CreateThreadsKK, "Create native/native threads");
    }


    printf("%s\n", ((passed) ? "PASS" : "FAIL"));

    PR_Cleanup();

    if (passed) {
        return 0;
    } else {
        return 1;
    }
}

installers/win32/Oolite_Readme.txt


How to run Oolite
-----------------

A folder has been created in Start -> Program Files called Oolite. This
folder has icons for running the game, the reference sheet, the Advice
for New Commanders guide, the link to the official Oolite website,a more
detailed ReadMe document in PDF format and an uninstall program.

To run the game, choose the Oolite icon in the Oolite folder.


The user preferences defaults file OoliteDefaults.plist
-----------------------------------------------------------------------

The file <installation dir>/oolite.app/GNUstep/Defaults/OoliteDefaults.plist
contains, among others, the current settings for fullscreen mode and display
resolutions, together with the user preference settings for sound volume,
reduced detail (Yes/No), wireframe graphics display (Yes/No) and the shader
effects level (Off, Simple, Full), in case your system supports shaders.
All these can be changed by either running the game and navigating to the
Game Options... menu ('F2' or '2' key, then select Game Options...), or
by directly editing the OoliteDefaults.plist file. The recommended way to
change settings is to use the in-game menu. See below for examples of
editing the preferences file. Note that OoliteDefaults.plist will not be
present after the game's installation. You will need to run Oolite at
least once to have it generated.


Switching between full screen and windowed mode, or changing resolution
-----------------------------------------------------------------------

If in doubt, delete OoliteDefaults.plist and restart the game. That will
start you in windowed mode.

To change the full screen mode resolution, you can use the Game Options...
menu or alternatively edit the OoliteDefaults.plist file by changing the
display_width and display_height values, and ensuring the fullscreen
property has a value of YES.


OoliteDefaults.plist Editing Examples
-----------------------------------------------------------------------

These settings will give a full screen display of 800x600, about one
third sound volume, reduced detail set to No, wireframe graphics set
to Yes and shader effects set to Simple:

{
    display_width = 800;
    display_height = 600;
    fullscreen = YES;
    "reduced-detail-graphics" = NO;
    "shader-effects-level" = 2;
    volume_control = 0.26;
    "wireframe-graphics" = YES;
}

And these settings will give a full screen display of 1400x1050,
full sound volume, reduced detail set to No, wireframe graphics
set to No and shader effects set to Full:

{
    display_width = 1400;
    display_height = 1050;
    fullscreen = YES;
    "reduced-detail-graphics" = NO;
    "shader-effects-level" = 3;
    volume_control = 1;
    "wireframe-graphics" = NO;
}


Tips
----

* Read the installed "Oolite reference sheet" PDF for the controls

* More detailed information about the game can be found inside the Acrobat
  PDF OoliteReadMe file, already installed in your root Oolite folder

* Use Shift+Escape to quit the game

* You can read the Advice for New Commanders at the bottom of this file for
  a quick introduction to the game, with hints and tips


Links
-----
Oolite website at: https://oolite.space

Oolite Message Board at: http://www.aegidian.org/bb

Oolite Development Project Page at: https://github.com/OoliteProject

Browse the Oolite wiki at: http://wiki.alioth.net/index.php/Oolite_Main_Page

Get OXPs at https://oolite.space/oxps/ or use the in-game Expansion Pack Manager











Advice for New Commanders*
by Disembodied, 24-Mar-2008
---------------------------

It is an ancient mariner, 
and he stoppeth one of three... 

All right there! You just got your pilot�s ticket. Can I just say that your zip-clip
there doesn�t do you justice? You�re itching to get off and out into the big black, I
can tell; but we just got a few final once-overs before I can stamp that thing legal.
Shall we? 

So. You got yourself a brand and shiny-new Cobra Mark III. Cowell and MgRath�s finest,
yes siree: more�n sixty years since the first one rolled off the line right here on Lave,
and it�s still one of the best. An all-round ship, you get me? It ain�t the fastest, and
it ain�t the strongest, nor the most killing neither, and it definitely ain�t the biggest,
by a long shot, but a sweet little number in her own right, no error. 

Let�s take a tour around... Hoo boy, she is mint, ain�t she! I just love that new-ship
smell. Take a sniff, go on: yeah, well, most of them long-chain monomers is carcinogenic,
so don�t you snort too deep... 

Hah! I�m just funnin� ya, kid. If pulling a tick from sniffing the command console was all
a pilot had to worry about, life would be gravy! No, there�s more�n enough out there to kill
you plenty quick, if you don�t watch out, shiny new ship or no. 

I see a lot of blanks on this here board... I�m guessing your ship is, whadda they call it,
a basic model, yeah? Legal minimum? Uh-huh, I thought so. Man oh man, they shouldn�t oughta
let kids out in a machine like this; it�s a sin, is what it is. Some bandit takes a pop at
you, and what you got to hold your end up with? A Pulse Laser. A Pulse Laser�s one step up
from a penlight, kiddo. Oh, it�s a better defence than just harsh language, and there�s
always a chance you might be attacked by a really nervous pirate � but seriously: if you
ever want to shift that �Harmless� tag you better beef up your armaments, and soon! Beam
laser, minimum. Until then you�d best stick to the cop-end worlds: Democracies and Corporates,
Confederacies maybe if you�re feeling lucky, you hear me? You stay sharp, and maybe you�ll
stay alive.

See, right here is what I�m talking about: this is where you need to fit an ECM. Someone locks
a missile on you, you pop that sucker fast. Oh, I know there�s Hardheads out there, shielded
missiles proofed against countermeasures, but a good ECM can pop those too, if you�re lucky.
You get one of those running on you, you turn tail and run from it as fast as you can. A
warhead�s nasty, but nosense in giving it a kinetic advantage too, right? Keep slapping the ECM
as you go, if you�ve got the energy for it: if the first burst don�t kill it, maybe the next
one will.

Speaking of running... over here is where you�d control your Witchdrive Fuel Injectors, if�n
you had �em... dumps fuel straight from the tanks into the drive, and shoots you off like an
Oresquan on a hot date. Good for whatever ails ya, from pushing past a mass-lock to getting the
hell out of town!

Down here, now, this is your Fuel Scoop indicator... huh, �offline�, I see. Sure, sure, you
don�t think you�ll ever need to kiss the stars: why bother, when fuel�s cheaper than Celabiler
poetry? Well, maybe it�s true, and maybe it ain�t, but anyways this piece of kit scoops up more
than just sunshine. There�s scraps and salvage out there, kid, and good money to be had. Skim on
over the top and this puppy drops �em straight into the cargo bay. Pays for itself in no time.
Sweeps up Escape Pods, too: you get the chance to bring someone safe home, you take it � even if
it means dumping some of your own payload to take them on board. Look out for the other guys and
they�ll look out for you.

And... sweet Lord Giles on a gyrospider, they didn�t even fit you out with a Docking Computer!
�Optional Extra�, my shiny blue ass... Oh, sure, manual docking�s easy enough, but there�s a
knack to it. You gotta get that knack first, though. Practice it. Before you go anywhere,
practice it. Fly out to the station buoy, turn around and come back in again, until you got it
pat. And match the rotation: you put scrapes or dents or a big long greasy smear all over my bay,
and I will NOT be pleased...

Oh, there�s a whole bunch of other shit you can stick on here: a Scanner Targeting Enhancement,
for one, if you ever get yourself set up right for a firefight. Even before then, maybe: if you
can clock pirates before they start their run on you, that�s half the battle. Well, quarter of
the battle. Or a fifth. Some proportion, anyhow. The Advanced Space Compass, too, now that�s a
handy doodad to have on board. And an Extra Energy Unit to boost your recharge. And Shield
Boosters, now they�re a no-brainer. And � okay, most of this junk is too high-tech for Lave: you
can get most everything at Zaonce, though, just a wormhole away. Dull kinda burg, Zaonce, but
they know their quarks from their quaternions. Shouldn�t set you back more�n ten, twenty thou.

You got how much? One hundred creds. One ... hundred ... creds. Ayoha. All right then. Let�s
break it down. Your problem here is financial, not technical. Maybe at bottom it�s psychological,
but I�ll give you the benefit.

There�s two types of money, kid: fast, and slow. Fast money comes easy, and slow money comes hard.
The slow is sure and steady, though, and the fast, well, it might make you wish you had waited.
I�ll run you through them both, though, and you can make up your own mind.

First of all, for the fast money, there�s this sweet and cherry Cobra III: you sell it, right now,
you�ll net yourself enough to buy a second-hand ship with enough scratch left over for some half-
decent kit. �Course, some of these second-hand numbers are pretty, well, used, if you know what I 
mean, and come with problems of their own. I mean, you ever try to take a dump in a head designed
for some other guy�s anatomy? And the resale sucks, if�n you ever want to move on up. But it�s an
option.

Second, now, there�s the... ah, let me just check that we�re alone here... okay: there�s the Black
Monks. Great guys, I�d like to make that clear, absolutely: most fine and upstanding! They�ll be
happy to loan you what you need to get you started. They�re a not-for-profit organisation, a charity,
really, but what with overheads and all they do have to charge a wee bit of interest on any loans
they make: and they are keen � eager, even � to see that they get paid back. You take a loan from
them, you make every gram of cargo pay, every time. Work hard though and it can be done: in all my
years I�ve never met anyone who defaulted on a loan from the Bank of St Herod. Not one. Ever.

Slow money, now, that�s less chancy. You buy up what�s cheap, you take it to where it�s expensive,
and you sell it at a profit. Rinse and repeat. What�s cheap where, and what�s expensive? Supply and
demand, kid. Like the philosopher said, �it�s the economy, stupid�. Agricultural worlds produce raw
materials like minerals, metals and radioactives, and the bio-products like food, textiles, booze
and furs, too. Industrial planets make finished goods, like luxuries, computers and machinery. So
you take the produce of one and you sell it on the other, and chances are you�re making money on
the deal. Politics don�t matter squat: farmers need harvesters and factories need feedstock!

O�course, money matters: rich Industrials are rich because they�ve got the most efficient processes,
so not only do they make the cheapest products, their factories are the hungriest and they�ll pay
the best prices for raw materials. Poor Agriculturals, on the other hand, they�re most desperate for
fine articles and will scrape together whatever they can to pay for �em: meanwhile, they�ll offer
you the cheapest deals anywhere for what they make themselves. Which puts a vicious lock on the
poverty trap, but hey: nobody said life was fair. Folks like you who�ve climbed up the gravity well,
you�re just filling a need. Buy and sell between rich Industrials and poor Agriculturals, that�s my
advice! There�s money to be made elsewhere, no error, but those are the sweetest runs you�re likely
to hit on. Bulk is the key, kid: the more you carry, the more you make. This Cobra III here can take
twenty tons, right now: for just 400 creds more you can get a Cargo Bay Expansion to take you up to
thirty-five.That extra fifteen tons of space will pay for itself and more in one good run, if you
can fill it up.

It ain�t all bulk, though. Watch the board for cheap deals on precious metals and gemstones: they
might not offer the greatest profits, but they don�t take up any cargo space at all. See this safe
over here, behind this bulkhead? You take on platinum, or gold, or a sack of IOUN gemstones when
you�re docked, they go right in here. You can keep �em here as long as you like, until you find
somewhere to offload �em. Co-op rules stop you dropping too much of �em, or too much of anything,
come to that, in one station � so much for free trade! � but as a slow-burn money-maker there�s not
much to beat it. You can mine for �em yourself, if�n you get a Mining Laser and an Ore Processor to
go with your Fuel Scoop, and you don�t mind scraping carbon scoring off the scoop every few jumps.
Only don�t, for any sake, put the Mining Laser on the nose! It�s a tool, not a weapon. Or you can
just buy the shinies cheap off the miners direct, if you run across a Rock Hermit. Powerful fond of
liquor, Rock Hermits are, too.

What �other� products? What you winking for, kid? You mean slaves, narcotics and firearms? Why don�t
you just damn well say so? They ain�t illegal. They�s what we call controlled merchandise. Bring as
much of �em in as you want... what will get you into trouble with the Blues is shipping them out of
a main system station. But there�s plenty of other places to buy �em up, all nice and legal, along
with reg�lar trade goods, too. Some of the Commie worlds have Slap-Yous and Cee-Zed-Gee-Effs, whatever
the hell they all are, and Astro-Gulags too, which are just plain depressing. Some industrial
Dictatorship systems, they got Imperial AstroFactories, although some of �em seem to sell stuff they
don�t ever make... go figure. And some spots, if they got the population size to make it worthwhile,
there�s Convenience Stores way out by the Witchpoint. You want to give these guys a try, you sail on
in. Check the system prices first, note down what you got yourself, see what�s on offer, and do the
sums.

There�s long-range shipping contracts on offer, too, in some stations: F8-F8 will bring �em up, if
there�s any there. You buy the deal and then get paid a bonus if you make the delivery on time.
They�ll be out your price-range just now, and anyway most of �em call for a bigger cargo-hold than
a Cobra can carry. Keep an eye out for any you might be able to do, though; if you build a rep as a
reliable carrier then the jobs can get real juicy.

That�s slow money, kid: work, save, invest, and work again, that�s what it�s all about! It ain�t pretty
but it gets you there in the end.

One final tip, kid: I�ll say this �cos I like ya. It won�t save you work but it will save you time,
and it might just save your life, too: if you want to get from the Witchpoint to the station fast,
without getting your jumpdrive mass-locked by anyone, friendly or otherwise, here�s what you do. Line
up on the planet; angle up away from it by near enough ninety degrees; then hit the Torus jumpdrive
and scoot on out of the main spacelane for a few hundred klicks or so. Then, when you�ve given yourself
enough sky, pull the nose back round and come on down to the station. Chances are you won�t meet a soul,
whether you�re cruising into Ensoreus or creeping into Qudira. The spacelanes is where the action is,
where there�s help and hostility both; you get nervous, you go off-beam. Most times, you�ll come through
safe.

Huh. Anyhow. I�m a busy frog, I can�t stay here all day filling in every Jameson on what they should have
learned in the spawning pond. Gimme your ticket, kid, and I�ll stamp it flight-ready, though Giles knows I
prob�ly shouldn�t... there ya go. That�s you ready to take on the Witch. Jens help us all... don�t know
enough to keep a level bearing through a wormhole... what they send up here for us to deal with... pick up
the pieces more like...


---------------------------
*Disclaimer: 
The above text makes reference to certain Oolite eXpansion Packs (OXPs), that are not part of the core
Oolite game. The fact that certain elements from OXPs are mentioned does not necessarily mean that
these OXPs are recommended by the Oolite Team, as OXP selection and usage is subject to user personal
preferences. The OXPs mentioned in Advice for New Commanders are Rusties, Bank of the Black Monks,
Ore Processor, Communist flavour pack, Dictatorship flavour pack, Your Ad Here. All Oolite OXPs are
available for download from https://oolite.space/oxps/ or from the in-game Expansion Pack Manager.

src/Core/NSThreadOOExtensions.h

/*

NSThreadOOExtensions.h

Utility methods for NSThread.

 
Copyright (C) 2007-2013 Jens Ayton

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

#import <Foundation/Foundation.h>
#import "OOFunctionAttributes.h"


@interface NSThread (OOExtensions)

//	Set name of current thread for identification during debugging.
//	Under OS X, this does more than -setName:.
+ (void) ooSetCurrentThreadName:(NSString *)name;

@end

src/Core/NSThreadOOExtensions.m

/*

NSThreadOOExtensions.m

 
Copyright (C) 2007-2013 Jens Ayton

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

#import "NSThreadOOExtensions.h"
#import "OOCocoa.h"
#include <pthread.h>


#define OO_HAVE_PTHREAD_SETNAME_NP	OOLITE_MAC_OS_X


@implementation NSThread (OOExtensions)

+ (void) ooSetCurrentThreadName:(NSString *)name
{
	// We may be called with no pool in place.
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	[[NSThread currentThread] setName:name];
	
#if OO_HAVE_PTHREAD_SETNAME_NP
	/*	Under Mac OS X 10.6, the name set by pthread_setname_np() is used in
		crash reports, but, annoyingly, -[NSThread setName:] does not call it.
	*/
	pthread_setname_np([name UTF8String]);
#endif
	
	[pool release];
}

@end

tests/Checklist-files/README.TXT

This directory contains support files for the testing checklist. See
Docs/CHECKLIST.TXT for more information.

tests/Readme.md

# Oolite testing files
A mixture of different testing thingies for Oolite.

* Checklist-files: saved games and reference screen shots for the testing checklist, found in [oolite/Doc/CHECKLIST.txt](https://github.com/OoliteProject/oolite/blob/master/Doc/CHECKLIST.txt).
* mac-build-clean: a script to perform a clean build of every Oolite configuration under Mac OS X.
* plistSchemaValidator: a command-line tool for testing plists against schemata in Oolite’s under-used plist schema language.
* priorityQueue: ad-hoc tests for `OOPriorityQueue`. Should be turned into unit tests.
* probabilitySetTest: ad-hoc tests for `OOProbabilitySet`. Should be turned into unit tests.
* scaling: test cases for the texture scaler. Should be turned into an OXP.
* test-oxps: several OXPs for in-game testing.

tests/mac-build-clean/README.txt

build-clean.sh

This script will check out a clean copy of Oolite trunk, and build four copies
of it:
* Debug-i386
* Debug-x86_64
* TestRelease (universal)
* Deployment (universal)

The working copy is made in a directory called "clean" within the current
working directory, which will be deleted first if it already exists. Build
results are written to text files inside the working directory.

As you may imagine, this is slow. On my 2007 iMac, it takes about 25 minutes.
If you show off about it being much faster on your machine, I'll force you to
do it nightly.

Because it builds a debug build for each supported architecture, and the
build process involves running code-generation tools, it must be run on a
64-bit Mac.

If you plan on running this, I suggest excluding the enclosing directory from
Time Machine backups.

tests/test-oxps/AI overflow test/Read me.txt

Test case for AI stack overflow behaviour.

Usage: :spawn ahruman-stack-overflow-test
    or system.addShips("ahruman-stack-overflow-test", 1, player.ship.position, 10000);

This will immediately trigger a setAITo: recursion.

tests/test-oxps/PNGTestSuite/README

This OXP runs through the 153 non-corrupt images in Willem van Schaik's PNG
test suite. The licensing terms of the test suite are unspecified, so the
images are not included. Download them from:
ftp://anonymous@ftp.simplesystems.org/pub/libpng/png/images/suite/PngSuite.tar.gz

The test suite's home page is:
http://libpng.org/pub/png/pngsuite.html

tests/test-oxps/RetroMissions/Read Me.txt

RetroMissions.oxp contains unmodified Oolite 1.65 scripts for regression testing of the legacy script engine.

Equipment

Name Visible Cost [deci-credits] Tech-Level
Advanced Space Compass yes 6500 8+
Advanced Navigational Array yes 22500 7+
Large Cargo Bay yes 4000 2+
Cloaking Device yes 500000 16+
Docking Computers yes 15000 10+
E.C.M. System yes 6000 3+
Extra Energy Unit yes 15000 9+
Escape Pod yes 10000 7+
Fuel yes 2 1+
Witchdrive Fuel Injectors yes 6000 11+
Fuel Scoops yes 5250 6+
Galactic Hyperdrive yes 50000 11+
ECM Hardened Missile yes 3500 10+
External Heat Shielding yes 15000 5+
Integrated Targeting System yes 15000 12+
Military Anti-Scanner Countermeasures (MASC'M) yes 1500000 1+
Military Scanner Filtering yes 250000 1+
Missile yes 300 2+
Unmount and sell all pylon mounted weapons yes 200 2+
Multi-Targeting System yes 3250 6+
Naval Energy Unit yes 500000 14+
Military Shield Enhancement yes 475500 14+
Tutorial Controls no 500000 101+
Passenger Berth - takes up 5t of cargo space yes 8250 6+
Remove Passenger Berth - reclaims 5t of cargo space yes 1000 2+
Quirium Cascade Mine yes 25000 7+
Maintenance Overhaul yes 1000 7+
Scanner Targeting Enhancement yes 4500 12+
Shield Boosters yes 147500 11+
Shield Enhancers yes 147500 101+
Target System Memory Expansion yes 12500 9+
Thargon yes 1000 101+
Trumble no 300 101+
Beam Laser yes 10000 5+
Military Laser yes 60000 11+
Mining Laser yes 8000 11+
Remove Laser yes 0 4+
Pulse Laser yes 4000 4+
Thargoid Laser yes 150000 101+
Wormhole Scanner yes 23950 10+
Thargon yes 1000 101+

Ships

Name
adder
adder-player
alloy
anaconda
anaconda-pirate
anaconda-player
Arc Detail
asp
asp-cloaked
asp-player
asteroid
asteroid-alternative
Ball Turret
barrel
boa
boa-mk2
boa-mk2-pirate
boa-mk2-player
boa-pirate
boa-player
boulder
boulder-alternative
buoy
buoy-witchpoint
cloaking-device
cobra3-alternate
cobra3-pirate
cobra3-player
cobra3-trader
cobramk1
cobramk1-alt
cobramk1-miner
cobramk1-player
constrictor
coriolis-station
Docking Slit (Vertical)
Docking Slit (horizontal)
dodecahedron-station
ecm-proof-missile
escape-capsule
ferdelance
ferdelance-player
gecko
Docking Slit
Rock Hermit living area
icosahedron-station
krait
mamba
mamba-escort
missile
moray
moray-player
morayMED
morayMED-player
more-wreckage2
more-wreckage3
more-wreckage4
more-wreckage5
oolite-cargopod-virtual
oolite-cinder
oolite-cinder-alternative
oolite-cinder-small
oolite-cinder-small-alternative
oolite-cobra3-strict
Docking Slit (virtual)
oolite-tutorial-asteroid
oolite-tutorial-buoy
oolite-tutorial-krait
oolite-tutorial-krait-wave1
oolite-tutorial-station
Question Mark
Navigation Buoy
Coriolis Dock
Coriolis Faceplate
Coriolis Triangle faces
Dodo Dock
Dodo Faceplate
Ico Dock
Ico Mainhull
Docking Slit
Rock Hermit (pipes)
Rock Hermit (rock)
Rock Hermit (tunnel)
Adder
oolite_template_adder-player
Metal fragment
Anaconda
oolite_template_anaconda-pirate
oolite_template_anaconda-player
Asp Mark II
oolite_template_asp-cloaked
oolite_template_asp-player
Asteroid
oolite_template_asteroid_alt
Cargo container
Boa
Boa Class Cruiser
oolite_template_boa-mk2-pirate
oolite_template_boa-mk2-player
oolite_template_boa-pirate
oolite_template_boa-player
Boulder
oolite_template_boulder_alt
Navigation Buoy
Witchpoint Beacon
oolite_template_cinder
oolite_template_cinder-small
oolite_template_cinder-small_alt
oolite_template_cinder_alt
Unusual cargo container
Cobra Mark III
oolite_template_cobra3-alternate
oolite_template_cobra3-pirate
oolite_template_cobra3-player
oolite_template_cobra3-trader
Cobra Mark I
oolite_template_cobramk1-alt
oolite_template_cobramk1-miner
oolite_template_cobramk1-player
Constrictor
Coriolis Station
Dodecahedron Station
ECM Hardened Missile
Escape capsule
Fer-de-Lance
oolite_template_ferdelance-player
Gecko
Icosahedron Station
Krait
Mamba
Mamba Escort
Missile
Moray Star Boat
oolite_template_moray-player
Moray Medical Boat
Moray Medical Boat
Python
oolite_template_python-blackdog
oolite_template_python-player
oolite_template_python-trader
Quirium Cascade Mine
Rock Hermit
oolite_template_rock-hermit-chaotic
oolite_template_rock-hermit-pirate
oolite_template_scarred-alloy
Orbital Shuttle
Sidewinder Scout Ship
oolite_template_sidewinder-escort
Splinter
oolite_template_splinter_alt
Thargoid Robot Fighter
Thargoid Warship
Transporter
Mining Transporter
Training Asteroid
Training Buoy
Training Fighter
oolite_template_tutorial-krait-wave1
Training Station
GalCop Viper
GalCop Viper Interceptor
oolite_template_viper-pursuit
Worm
oolite_template_worm-miner
oolite_template_wreckage-chunk
Wreckage
python
python-blackdog
python-player
python-trader
qbomb
rock-hermit
rock-hermit-chaotic
rock-hermit-pirate
scarred-alloy
shuttle
sidewinder
sidewinder-escort
splinter
splinter-alternative
Strut 10-10-30
tharglet
thargoid
transporter
transporter-miner
viper
viper-interceptor
viper-pursuit
worm
worm-miner
wreckage-chunk
wreckage-chunk2
wreckage-chunk3
wreckage-component

Models

This expansion declares no models. This may be related to warnings.

Scripts

This expansion declares no scripts.