From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH v3 9/9] index-helper: add Windows support
Date: Mon, 28 Jul 2014 19:03:15 +0700 [thread overview]
Message-ID: <1406548995-28549-10-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1406548995-28549-1-git-send-email-pclouds@gmail.com>
Windows supports shared memory, but the semantics is a bit different
than POSIX shm. The most noticeable thing is there's no way to get the
shared memory's size by the reader, and wrapping fstat to do that
would be hell. So the shm size is added near the end, hidden away from
shm users (storing it in headers would cause more problems with munmap,
storing it as a separate shm is even worse).
PostMessage is used instead of UNIX signals for notification.
Lightweight (at least code-wise) on the client side.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
config.mak.uname | 2 ++
index-helper.c | 48 ++++++++++++++++++++++++++++
read-cache.c | 6 ++++
shm.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 152 insertions(+)
diff --git a/config.mak.uname b/config.mak.uname
index 7e66d80..74e764f 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -377,6 +377,7 @@ ifndef DEBUG
else
BASIC_CFLAGS += -Zi -MDd
endif
+ PROGRAM_OBJS += index-helper.o
X = .exe
endif
ifeq ($(uname_S),Interix)
@@ -532,6 +533,7 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
else
NO_CURL = YesPlease
endif
+ PROGRAM_OBJS += index-helper.o
endif
ifeq ($(uname_S),QNX)
COMPAT_CFLAGS += -DSA_RESTART=0
diff --git a/index-helper.c b/index-helper.c
index 4262678..7c2a0e7 100644
--- a/index-helper.c
+++ b/index-helper.c
@@ -147,6 +147,51 @@ static void loop(const char *pid_file, int idle_in_seconds)
; /* do nothing, all is handled by signal handlers already */
}
+#elif defined(GIT_WINDOWS_NATIVE)
+
+static void loop(const char *pid_file, int idle_in_seconds)
+{
+ HWND hwnd;
+ UINT_PTR timer = 0;
+ MSG msg;
+ HINSTANCE hinst = GetModuleHandle(NULL);
+ WNDCLASS wc;
+
+ /*
+ * Emulate UNIX signals by sending WM_USER+x to a
+ * window. Register window class and create a new window to
+ * catch these messages.
+ */
+ memset(&wc, 0, sizeof(wc));
+ wc.lpfnWndProc = DefWindowProc;
+ wc.hInstance = hinst;
+ wc.lpszClassName = "git-index-helper";
+ if (!RegisterClass(&wc))
+ die_errno(_("could not register new window class"));
+
+ hwnd = CreateWindow("git-index-helper", pid_file,
+ 0, 0, 0, 1, 1, NULL, NULL, hinst, NULL);
+ if (!hwnd)
+ die_errno(_("could not register new window"));
+
+ refresh(0);
+ while (1) {
+ timer = SetTimer(hwnd, timer, idle_in_seconds * 1000, NULL);
+ if (!timer)
+ die(_("no timer!"));
+ if (!GetMessage(&msg, hwnd, 0, 0) || msg.message == WM_TIMER)
+ break;
+ switch (msg.message) {
+ case WM_USER:
+ refresh(0);
+ break;
+ default:
+ /* just reset the timer */
+ break;
+ }
+ }
+}
+
#else
static void loop(const char *pid_file, int idle_in_seconds)
@@ -192,6 +237,9 @@ int main(int argc, char **argv)
git_path("index-helper.pid"),
LOCK_DIE_ON_ERROR);
strbuf_addf(&sb,
+#ifdef GIT_WINDOWS_NATIVE
+ "HWND"
+#endif
"%" PRIuMAX, (uintmax_t) getpid());
write_in_full(fd, sb.buf, sb.len);
commit_lock_file(&lock);
diff --git a/read-cache.c b/read-cache.c
index d6eb17f..0ca3345 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1489,6 +1489,12 @@ static void poke_daemon(const struct stat *st, int refresh_cache)
pid_t pid = strtoul(sb.buf, &end, 10);
if (end && sb.buf + st->st_size == end)
kill(pid, refresh_cache ? SIGHUP : SIGUSR1);
+#elif defined(GIT_WINDOWS_NATIVE)
+ if (starts_with(sb.buf, "HWND")) {
+ HWND hwnd = FindWindow("git-index-helper", sb.buf);
+ PostMessage(hwnd, refresh_cache ? WM_USER : WM_USER + 1,
+ 0, 0);
+ }
#endif
}
close(fd);
diff --git a/shm.c b/shm.c
index 4ec1a00..04d8a35 100644
--- a/shm.c
+++ b/shm.c
@@ -52,6 +52,102 @@ void git_shm_unlink(const char *fmt, ...)
shm_unlink(path);
}
+#elif defined(GIT_WINDOWS_NATIVE)
+
+#define SHM_PATH_LEN 82 /* a little bit longer than POSIX because of "Local\\" */
+
+static ssize_t create_shm_map(int oflag, int perm, ssize_t length,
+ void **mmap, int prot, int flags,
+ const char *path, unsigned long page_size)
+{
+ size_t real_length;
+ void *last_page;
+ HANDLE h;
+
+ assert(perm == 0700);
+ assert(oflag == (O_CREAT | O_EXCL | O_RDWR));
+ assert(prot == (PROT_READ | PROT_WRITE));
+ assert(flags == MAP_SHARED);
+ assert(length >= 0);
+
+ real_length = length;
+ if (real_length % page_size)
+ real_length += page_size - (real_length % page_size);
+ real_length += page_size;
+ h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
+ real_length, path);
+ if (!h)
+ return -1;
+ *mmap = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, real_length);
+ CloseHandle(h);
+ if (!*mmap)
+ return -1;
+ last_page = (unsigned char *)*mmap + real_length - page_size;
+ *(unsigned long *)last_page = length;
+ return length;
+}
+
+static ssize_t open_shm_map(int oflag, int perm, ssize_t length, void **mmap,
+ int prot, int flags, const char *path,
+ unsigned long page_size)
+{
+ void *last_page;
+ HANDLE h;
+
+ assert(perm == 0700);
+ assert(oflag == O_RDONLY);
+ assert(prot == PROT_READ);
+ assert(flags == MAP_SHARED);
+ assert(length <= 0);
+
+ h = OpenFileMapping(FILE_MAP_READ, FALSE, path);
+ if (!h)
+ return -1;
+ *mmap = MapViewOfFile(h, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(h);
+ if (!*mmap)
+ return -1;
+ if (length < 0) {
+ MEMORY_BASIC_INFORMATION mbi;
+ if (!VirtualQuery(*mmap, &mbi, sizeof(mbi))) {
+ UnmapViewOfFile(*mmap);
+ return -1;
+ }
+ if (mbi.RegionSize % page_size)
+ die("expected size %lu to be %lu aligned",
+ mbi.RegionSize, page_size);
+ last_page = (unsigned char *)*mmap + mbi.RegionSize - page_size;
+ length = *(unsigned long *)last_page;
+ }
+ return length;
+}
+
+ssize_t git_shm_map(int oflag, int perm, ssize_t length, void **mmap,
+ int prot, int flags, const char *fmt, ...)
+{
+ SYSTEM_INFO si;
+ va_list ap;
+ char path[SHM_PATH_LEN];
+
+ GetSystemInfo(&si);
+
+ strcpy(path, "Local\\");
+ va_start(ap, fmt);
+ vsprintf(path + strlen(path), fmt, ap);
+ va_end(ap);
+
+ if (oflag & O_CREAT)
+ return create_shm_map(oflag, perm, length, mmap, prot,
+ flags, path, si.dwPageSize);
+ else
+ return open_shm_map(oflag, perm, length, mmap, prot,
+ flags, path, si.dwPageSize);
+}
+
+void git_shm_unlink(const char *fmt, ...)
+{
+}
+
#else
ssize_t git_shm_map(int oflag, int perm, ssize_t length, void **mmap,
--
2.1.0.rc0.66.gb9187ad
prev parent reply other threads:[~2014-07-28 12:04 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-28 12:03 [PATCH v3 0/9] Speed up cache loading time Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` [PATCH v3 1/9] trace.c: add GIT_TRACE_PACK_STATS for pack usage statistics Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` [PATCH v3 2/9] read-cache.c: fix constness of verify_hdr() Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` [PATCH v3 3/9] read-cache: allow to keep mmap'd memory after reading Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` [PATCH v3 4/9] index-helper: new daemon for caching index and related stuff Nguyễn Thái Ngọc Duy
2014-07-30 8:08 ` Eric Sunshine
2014-07-30 10:39 ` Duy Nguyen
2014-07-31 2:41 ` David Turner
2014-07-28 12:03 ` [PATCH v3 5/9] trace.c: add GIT_TRACE_INDEX_STATS for index statistics Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` [PATCH v3 6/9] index-helper: add --strict Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` [PATCH v3 7/9] daemonize(): set a flag before exiting the main process Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` [PATCH v3 8/9] index-helper: add --detach Nguyễn Thái Ngọc Duy
2014-07-28 12:03 ` Nguyễn Thái Ngọc Duy [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1406548995-28549-10-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).