asyncengine 0.0.1.testing1 → 0.0.2.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -21,6 +21,7 @@
21
21
 
22
22
  #include <assert.h>
23
23
  #include <direct.h>
24
+ #include <limits.h>
24
25
  #include <malloc.h>
25
26
  #include <stdio.h>
26
27
  #include <string.h>
@@ -29,9 +30,10 @@
29
30
 
30
31
  #include "uv.h"
31
32
  #include "internal.h"
32
- #include "tlhelp32.h"
33
- #include "psapi.h"
34
- #include "iphlpapi.h"
33
+
34
+ #include <iphlpapi.h>
35
+ #include <psapi.h>
36
+ #include <tlhelp32.h>
35
37
 
36
38
 
37
39
  /*
@@ -46,11 +48,32 @@
46
48
  */
47
49
  #define MAX_TITLE_LENGTH 8192
48
50
 
51
+ /* The number of nanoseconds in one second. */
52
+ #undef NANOSEC
53
+ #define NANOSEC 1000000000
54
+
49
55
 
56
+ /* Cached copy of the process title, plus a mutex guarding it. */
50
57
  static char *process_title;
51
- static uv_once_t uv_process_title_init_guard_ = UV_ONCE_INIT;
52
58
  static CRITICAL_SECTION process_title_lock;
53
59
 
60
+ /* The tick frequency of the high-resolution clock. */
61
+ static uint64_t hrtime_frequency_ = 0;
62
+
63
+
64
+ /*
65
+ * One-time intialization code for functionality defined in util.c.
66
+ */
67
+ void uv__util_init() {
68
+ /* Initialize process title access mutex. */
69
+ InitializeCriticalSection(&process_title_lock);
70
+
71
+ /* Retrieve high-resolution timer frequency. */
72
+ if (!QueryPerformanceFrequency((LARGE_INTEGER*) &hrtime_frequency_))
73
+ hrtime_frequency_ = 0;
74
+ }
75
+
76
+
54
77
  int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size,
55
78
  char* utf8Buffer, size_t utf8Size) {
56
79
  return WideCharToMultiByte(CP_UTF8,
@@ -75,133 +98,182 @@ int uv_utf8_to_utf16(const char* utf8Buffer, wchar_t* utf16Buffer,
75
98
  }
76
99
 
77
100
 
78
- int uv_exepath(char* buffer, size_t* size) {
79
- int retVal;
80
- size_t utf16Size;
81
- wchar_t* utf16Buffer;
101
+ int uv_exepath(char* buffer, size_t* size_ptr) {
102
+ int utf8_len, utf16_buffer_len, utf16_len;
103
+ WCHAR* utf16_buffer;
82
104
 
83
- if (!buffer || !size) {
105
+ if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {
84
106
  return -1;
85
107
  }
86
108
 
87
- utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * *size);
88
- if (!utf16Buffer) {
89
- retVal = -1;
90
- goto done;
109
+ if (*size_ptr > 32768) {
110
+ /* Windows paths can never be longer than this. */
111
+ utf16_buffer_len = 32768;
112
+ } else {
113
+ utf16_buffer_len = (int) *size_ptr;
91
114
  }
92
115
 
93
- /* Get the path as UTF-16 */
94
- utf16Size = GetModuleFileNameW(NULL, utf16Buffer, *size - 1);
95
- if (utf16Size <= 0) {
96
- /* uv__set_sys_error(loop, GetLastError()); */
97
- retVal = -1;
98
- goto done;
116
+ utf16_buffer = (wchar_t*) malloc(sizeof(WCHAR) * utf16_buffer_len);
117
+ if (!utf16_buffer) {
118
+ return -1;
99
119
  }
100
120
 
101
- utf16Buffer[utf16Size] = L'\0';
102
-
103
- /* Convert to UTF-8 */
104
- *size = uv_utf16_to_utf8(utf16Buffer, utf16Size, buffer, *size);
105
- if (!*size) {
106
- /* uv__set_sys_error(loop, GetLastError()); */
107
- retVal = -1;
108
- goto done;
121
+ /* Get the path as UTF-16. */
122
+ utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);
123
+ if (utf16_len <= 0) {
124
+ goto error;
109
125
  }
110
126
 
111
- buffer[*size] = '\0';
112
- retVal = 0;
127
+ /* utf16_len contains the length, *not* including the terminating null. */
128
+ utf16_buffer[utf16_len] = L'\0';
113
129
 
114
- done:
115
- if (utf16Buffer) {
116
- free(utf16Buffer);
117
- }
130
+ /* Convert to UTF-8 */
131
+ utf8_len = WideCharToMultiByte(CP_UTF8,
132
+ 0,
133
+ utf16_buffer,
134
+ -1,
135
+ buffer,
136
+ *size_ptr > INT_MAX ? INT_MAX : (int) *size_ptr,
137
+ NULL,
138
+ NULL);
139
+ if (utf8_len == 0) {
140
+ goto error;
141
+ }
142
+
143
+ free(utf16_buffer);
144
+
145
+ /* utf8_len *does* include the terminating null at this point, but the */
146
+ /* returned size shouldn't. */
147
+ *size_ptr = utf8_len - 1;
148
+ return 0;
118
149
 
119
- return retVal;
150
+ error:
151
+ free(utf16_buffer);
152
+ return -1;
120
153
  }
121
154
 
122
155
 
123
156
  uv_err_t uv_cwd(char* buffer, size_t size) {
124
- uv_err_t err;
125
- size_t utf8Size;
126
- wchar_t* utf16Buffer = NULL;
157
+ DWORD utf16_len;
158
+ WCHAR utf16_buffer[MAX_PATH];
159
+ int r;
127
160
 
128
- if (!buffer || !size) {
129
- err.code = UV_EINVAL;
130
- goto done;
161
+ if (buffer == NULL || size == 0) {
162
+ return uv__new_artificial_error(UV_EINVAL);
131
163
  }
132
164
 
133
- utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * size);
134
- if (!utf16Buffer) {
135
- err.code = UV_ENOMEM;
136
- goto done;
137
- }
138
-
139
- if (!_wgetcwd(utf16Buffer, size - 1)) {
140
- err = uv__new_sys_error(_doserrno);
141
- goto done;
165
+ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
166
+ if (utf16_len == 0) {
167
+ return uv__new_sys_error(GetLastError());
168
+ } else if (utf16_len > MAX_PATH) {
169
+ /* This should be impossible; however the CRT has a code path to deal */
170
+ /* with this scenario, so I added a check anyway. */
171
+ return uv__new_artificial_error(UV_EIO);
142
172
  }
143
173
 
144
- utf16Buffer[size - 1] = L'\0';
174
+ /* utf16_len contains the length, *not* including the terminating null. */
175
+ utf16_buffer[utf16_len] = L'\0';
145
176
 
146
- /* Convert to UTF-8 */
147
- utf8Size = uv_utf16_to_utf8(utf16Buffer, -1, buffer, size);
148
- if (utf8Size == 0) {
149
- err = uv__new_sys_error(GetLastError());
150
- goto done;
177
+ /* The returned directory should not have a trailing slash, unless it */
178
+ /* points at a drive root, like c:\. Remove it if needed.*/
179
+ if (utf16_buffer[utf16_len - 1] == L'\\' &&
180
+ !(utf16_len == 3 && utf16_buffer[1] == L':')) {
181
+ utf16_len--;
182
+ utf16_buffer[utf16_len] = L'\0';
151
183
  }
152
184
 
153
- buffer[utf8Size] = '\0';
154
- err = uv_ok_;
155
-
156
- done:
157
- if (utf16Buffer) {
158
- free(utf16Buffer);
185
+ /* Convert to UTF-8 */
186
+ r = WideCharToMultiByte(CP_UTF8,
187
+ 0,
188
+ utf16_buffer,
189
+ -1,
190
+ buffer,
191
+ size > INT_MAX ? INT_MAX : (int) size,
192
+ NULL,
193
+ NULL);
194
+ if (r == 0) {
195
+ return uv__new_sys_error(GetLastError());
159
196
  }
160
197
 
161
- return err;
198
+ return uv_ok_;
162
199
  }
163
200
 
164
201
 
165
202
  uv_err_t uv_chdir(const char* dir) {
166
- uv_err_t err;
167
- wchar_t* utf16Buffer = NULL;
168
- size_t utf16Size;
169
-
170
- if (!dir) {
171
- err.code = UV_EINVAL;
172
- goto done;
173
- }
174
-
175
- utf16Size = uv_utf8_to_utf16(dir, NULL, 0);
176
- if (!utf16Size) {
177
- err = uv__new_sys_error(GetLastError());
178
- goto done;
179
- }
180
-
181
- utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * utf16Size);
182
- if (!utf16Buffer) {
183
- err.code = UV_ENOMEM;
184
- goto done;
203
+ WCHAR utf16_buffer[MAX_PATH];
204
+ size_t utf16_len;
205
+ WCHAR drive_letter, env_var[4];
206
+
207
+ if (dir == NULL) {
208
+ return uv__new_artificial_error(UV_EINVAL);
209
+ }
210
+
211
+ if (MultiByteToWideChar(CP_UTF8,
212
+ 0,
213
+ dir,
214
+ -1,
215
+ utf16_buffer,
216
+ MAX_PATH) == 0) {
217
+ DWORD error = GetLastError();
218
+ /* The maximum length of the current working directory is 260 chars, */
219
+ /* including terminating null. If it doesn't fit, the path name must be */
220
+ /* too long. */
221
+ if (error == ERROR_INSUFFICIENT_BUFFER) {
222
+ return uv__new_artificial_error(UV_ENAMETOOLONG);
223
+ } else {
224
+ return uv__new_sys_error(error);
225
+ }
185
226
  }
186
227
 
187
- if (!uv_utf8_to_utf16(dir, utf16Buffer, utf16Size)) {
188
- err = uv__new_sys_error(GetLastError());
189
- goto done;
228
+ if (!SetCurrentDirectoryW(utf16_buffer)) {
229
+ return uv__new_sys_error(GetLastError());
190
230
  }
191
231
 
192
- if (_wchdir(utf16Buffer) == -1) {
193
- err = uv__new_sys_error(_doserrno);
194
- goto done;
232
+ /* Windows stores the drive-local path in an "hidden" environment variable, */
233
+ /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
234
+ /* update this, so we'll have to do it. */
235
+ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
236
+ if (utf16_len == 0) {
237
+ return uv__new_sys_error(GetLastError());
238
+ } else if (utf16_len > MAX_PATH) {
239
+ return uv__new_artificial_error(UV_EIO);
240
+ }
241
+
242
+ /* The returned directory should not have a trailing slash, unless it */
243
+ /* points at a drive root, like c:\. Remove it if needed. */
244
+ if (utf16_buffer[utf16_len - 1] == L'\\' &&
245
+ !(utf16_len == 3 && utf16_buffer[1] == L':')) {
246
+ utf16_len--;
247
+ utf16_buffer[utf16_len] = L'\0';
248
+ }
249
+
250
+ if (utf16_len < 2 || utf16_buffer[1] != L':') {
251
+ /* Doesn't look like a drive letter could be there - probably an UNC */
252
+ /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
253
+ drive_letter = 0;
254
+ } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
255
+ drive_letter = utf16_buffer[0];
256
+ } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
257
+ /* Convert to uppercase. */
258
+ drive_letter = utf16_buffer[0] - L'a' + L'A';
259
+ } else {
260
+ /* Not valid. */
261
+ drive_letter = 0;
195
262
  }
196
263
 
197
- err = uv_ok_;
264
+ if (drive_letter != 0) {
265
+ /* Construct the environment variable name and set it. */
266
+ env_var[0] = L'=';
267
+ env_var[1] = drive_letter;
268
+ env_var[2] = L':';
269
+ env_var[3] = L'\0';
198
270
 
199
- done:
200
- if (utf16Buffer) {
201
- free(utf16Buffer);
271
+ if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {
272
+ return uv__new_sys_error(GetLastError());
273
+ }
202
274
  }
203
275
 
204
- return err;
276
+ return uv_ok_;
205
277
  }
206
278
 
207
279
 
@@ -265,17 +337,12 @@ char** uv_setup_args(int argc, char** argv) {
265
337
  }
266
338
 
267
339
 
268
- static void uv_process_title_init(void) {
269
- InitializeCriticalSection(&process_title_lock);
270
- }
271
-
272
-
273
340
  uv_err_t uv_set_process_title(const char* title) {
274
341
  uv_err_t err;
275
342
  int length;
276
343
  wchar_t* title_w = NULL;
277
344
 
278
- uv_once(&uv_process_title_init_guard_, uv_process_title_init);
345
+ uv__once_init();
279
346
 
280
347
  /* Find out how big the buffer for the wide-char title must be */
281
348
  length = uv_utf8_to_utf16(title, NULL, 0);
@@ -350,7 +417,7 @@ static int uv__get_process_title() {
350
417
 
351
418
 
352
419
  uv_err_t uv_get_process_title(char* buffer, size_t size) {
353
- uv_once(&uv_process_title_init_guard_, uv_process_title_init);
420
+ uv__once_init();
354
421
 
355
422
  EnterCriticalSection(&process_title_lock);
356
423
  /*
@@ -369,6 +436,31 @@ uv_err_t uv_get_process_title(char* buffer, size_t size) {
369
436
  }
370
437
 
371
438
 
439
+ uint64_t uv_hrtime(void) {
440
+ LARGE_INTEGER counter;
441
+
442
+ uv__once_init();
443
+
444
+ /* If the performance frequency is zero, there's no support. */
445
+ if (!hrtime_frequency_) {
446
+ /* uv__set_sys_error(loop, ERROR_NOT_SUPPORTED); */
447
+ return 0;
448
+ }
449
+
450
+ if (!QueryPerformanceCounter(&counter)) {
451
+ /* uv__set_sys_error(loop, GetLastError()); */
452
+ return 0;
453
+ }
454
+
455
+ /* Because we have no guarantee about the order of magnitude of the */
456
+ /* performance counter frequency, and there may not be much headroom to */
457
+ /* multiply by NANOSEC without overflowing, we use 128-bit math instead. */
458
+ return ((uint64_t) counter.LowPart * NANOSEC / hrtime_frequency_) +
459
+ (((uint64_t) counter.HighPart * NANOSEC / hrtime_frequency_)
460
+ << 32);
461
+ }
462
+
463
+
372
464
  uv_err_t uv_resident_set_memory(size_t* rss) {
373
465
  HANDLE current_process;
374
466
  PROCESS_MEMORY_COUNTERS pmc;
@@ -487,81 +579,148 @@ uv_err_t uv_uptime(double* uptime) {
487
579
 
488
580
 
489
581
  uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
490
- uv_err_t err;
491
- char key[128];
492
- HKEY processor_key = NULL;
493
- DWORD cpu_speed = 0;
494
- DWORD cpu_speed_length = sizeof(cpu_speed);
495
- char cpu_brand[256];
496
- DWORD cpu_brand_length = sizeof(cpu_brand);
582
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
583
+ DWORD sppi_size;
497
584
  SYSTEM_INFO system_info;
585
+ DWORD cpu_count, i, r;
586
+ ULONG result_size;
587
+ size_t size;
588
+ uv_err_t err;
498
589
  uv_cpu_info_t* cpu_info;
499
- unsigned int i;
500
590
 
501
- GetSystemInfo(&system_info);
591
+ *cpu_infos = NULL;
592
+ *count = 0;
502
593
 
503
- *cpu_infos = (uv_cpu_info_t*)malloc(system_info.dwNumberOfProcessors *
504
- sizeof(uv_cpu_info_t));
505
- if (!(*cpu_infos)) {
506
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
507
- }
594
+ uv__once_init();
508
595
 
509
- *count = 0;
596
+ GetSystemInfo(&system_info);
597
+ cpu_count = system_info.dwNumberOfProcessors;
510
598
 
511
- for (i = 0; i < system_info.dwNumberOfProcessors; i++) {
512
- _snprintf(key, sizeof(key), "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", i);
599
+ size = cpu_count * sizeof(uv_cpu_info_t);
600
+ *cpu_infos = (uv_cpu_info_t*) malloc(size);
601
+ if (*cpu_infos == NULL) {
602
+ err = uv__new_artificial_error(UV_ENOMEM);
603
+ goto out;
604
+ }
605
+ memset(*cpu_infos, 0, size);
513
606
 
514
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE,
515
- &processor_key) != ERROR_SUCCESS) {
516
- if (i == 0) {
517
- err = uv__new_sys_error(GetLastError());
518
- goto done;
519
- }
607
+ sppi_size = sizeof(*sppi) * cpu_count;
608
+ sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*) malloc(sppi_size);
609
+ if (!sppi) {
610
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
611
+ }
520
612
 
521
- continue;
613
+ r = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
614
+ sppi,
615
+ sppi_size,
616
+ &result_size);
617
+ if (r != ERROR_SUCCESS || result_size != sppi_size) {
618
+ err = uv__new_sys_error(GetLastError());
619
+ goto out;
620
+ }
621
+
622
+ for (i = 0; i < cpu_count; i++) {
623
+ WCHAR key_name[128];
624
+ HKEY processor_key;
625
+ DWORD cpu_speed;
626
+ DWORD cpu_speed_size = sizeof(cpu_speed);
627
+ WCHAR cpu_brand[256];
628
+ DWORD cpu_brand_size = sizeof(cpu_brand);
629
+
630
+ _snwprintf(key_name,
631
+ ARRAY_SIZE(key_name),
632
+ L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
633
+ i);
634
+
635
+ r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
636
+ key_name,
637
+ 0,
638
+ KEY_QUERY_VALUE,
639
+ &processor_key);
640
+ if (r != ERROR_SUCCESS) {
641
+ err = uv__new_sys_error(GetLastError());
642
+ goto out;
522
643
  }
523
644
 
524
- if (RegQueryValueEx(processor_key, "~MHz", NULL, NULL,
525
- (LPBYTE)&cpu_speed, &cpu_speed_length)
526
- != ERROR_SUCCESS) {
645
+ if (RegQueryValueExW(processor_key,
646
+ L"~MHz",
647
+ NULL, NULL,
648
+ (BYTE*) &cpu_speed,
649
+ &cpu_speed_size) != ERROR_SUCCESS) {
527
650
  err = uv__new_sys_error(GetLastError());
528
- goto done;
651
+ RegCloseKey(processor_key);
652
+ goto out;
529
653
  }
530
654
 
531
- if (RegQueryValueEx(processor_key, "ProcessorNameString", NULL, NULL,
532
- (LPBYTE)&cpu_brand, &cpu_brand_length)
533
- != ERROR_SUCCESS) {
655
+ if (RegQueryValueExW(processor_key,
656
+ L"ProcessorNameString",
657
+ NULL, NULL,
658
+ (BYTE*) &cpu_brand,
659
+ &cpu_brand_size) != ERROR_SUCCESS) {
534
660
  err = uv__new_sys_error(GetLastError());
535
- goto done;
661
+ RegCloseKey(processor_key);
662
+ goto out;
536
663
  }
537
664
 
538
665
  RegCloseKey(processor_key);
539
- processor_key = NULL;
540
666
 
541
667
  cpu_info = &(*cpu_infos)[i];
542
-
543
- /* $TODO: find times on windows */
544
- cpu_info->cpu_times.user = 0;
668
+ cpu_info->speed = cpu_speed;
669
+ cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
670
+ cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
671
+ sppi[i].IdleTime.QuadPart) / 10000;
672
+ cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;
673
+ cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
545
674
  cpu_info->cpu_times.nice = 0;
546
- cpu_info->cpu_times.sys = 0;
547
- cpu_info->cpu_times.idle = 0;
548
- cpu_info->cpu_times.irq = 0;
549
675
 
550
- cpu_info->model = strdup(cpu_brand);
551
- cpu_info->speed = cpu_speed;
676
+ size = uv_utf16_to_utf8(cpu_brand,
677
+ cpu_brand_size / sizeof(WCHAR),
678
+ NULL,
679
+ 0);
680
+ if (size == 0) {
681
+ err = uv__new_sys_error(GetLastError());
682
+ goto out;
683
+ }
684
+
685
+ /* Allocate 1 extra byte for the null terminator. */
686
+ cpu_info->model = (char*) malloc(size + 1);
687
+ if (cpu_info->model == NULL) {
688
+ err = uv__new_artificial_error(UV_ENOMEM);
689
+ goto out;
690
+ }
691
+
692
+ if (uv_utf16_to_utf8(cpu_brand,
693
+ cpu_brand_size / sizeof(WCHAR),
694
+ cpu_info->model,
695
+ size) == 0) {
696
+ err = uv__new_sys_error(GetLastError());
697
+ goto out;
698
+ }
699
+
700
+ /* Ensure that cpu_info->model is null terminated. */
701
+ cpu_info->model[size] = '\0';
552
702
 
553
703
  (*count)++;
554
704
  }
555
705
 
556
706
  err = uv_ok_;
557
707
 
558
- done:
559
- if (processor_key) {
560
- RegCloseKey(processor_key);
708
+ out:
709
+ if (sppi) {
710
+ free(sppi);
561
711
  }
562
712
 
563
- if (err.code != UV_OK) {
713
+ if (err.code != UV_OK &&
714
+ *cpu_infos != NULL) {
715
+ int i;
716
+
717
+ for (i = 0; i < *count; i++) {
718
+ /* This is safe because the cpu_infos memory area is zeroed out */
719
+ /* immediately after allocating it. */
720
+ free((*cpu_infos)[i].model);
721
+ }
564
722
  free(*cpu_infos);
723
+
565
724
  *cpu_infos = NULL;
566
725
  *count = 0;
567
726
  }
@@ -615,8 +774,13 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
615
774
  for (adapter_address = adapter_addresses;
616
775
  adapter_address != NULL;
617
776
  adapter_address = adapter_address->Next) {
777
+
778
+ if (adapter_address->OperStatus != IfOperStatusUp)
779
+ continue;
780
+
618
781
  unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
619
782
  adapter_address->FirstUnicastAddress;
783
+
620
784
  while (unicast_address) {
621
785
  (*count)++;
622
786
  unicast_address = unicast_address->Next;
@@ -634,6 +798,10 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
634
798
  for (adapter_address = adapter_addresses;
635
799
  adapter_address != NULL;
636
800
  adapter_address = adapter_address->Next) {
801
+
802
+ if (adapter_address->OperStatus != IfOperStatusUp)
803
+ continue;
804
+
637
805
  name = NULL;
638
806
  unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
639
807
  adapter_address->FirstUnicastAddress;
@@ -694,26 +862,3 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
694
862
 
695
863
  free(addresses);
696
864
  }
697
-
698
-
699
- void uv_filetime_to_time_t(FILETIME* file_time, time_t* stat_time) {
700
- FILETIME local_time;
701
- SYSTEMTIME system_time;
702
- struct tm time;
703
-
704
- if ((file_time->dwLowDateTime || file_time->dwHighDateTime) &&
705
- FileTimeToLocalFileTime(file_time, &local_time) &&
706
- FileTimeToSystemTime(&local_time, &system_time)) {
707
- time.tm_year = system_time.wYear - 1900;
708
- time.tm_mon = system_time.wMonth - 1;
709
- time.tm_mday = system_time.wDay;
710
- time.tm_hour = system_time.wHour;
711
- time.tm_min = system_time.wMinute;
712
- time.tm_sec = system_time.wSecond;
713
- time.tm_isdst = -1;
714
-
715
- *stat_time = mktime(&time);
716
- } else {
717
- *stat_time = 0;
718
- }
719
- }