I think it's safe to drop this patch now. It's mostly to prove that it could work on Windows. But I don't think it's tested a lot (even I only occasionally test it under wine). On Thu, Mar 10, 2016 at 1:36 AM, David Turner <dturner@xxxxxxxxxxxxxxxx> wrote: > From: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> > > 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@xxxxxxxxx> > --- > config.mak.uname | 2 ++ > index-helper.c | 48 ++++++++++++++++++++++++++++ > read-cache.c | 13 ++++++++ > shm.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 159 insertions(+) > > diff --git a/config.mak.uname b/config.mak.uname > index b5108e1..49320c7 100644 > --- a/config.mak.uname > +++ b/config.mak.uname > @@ -394,6 +394,7 @@ ifndef DEBUG > else > BASIC_CFLAGS += -Zi -MDd > endif > + PROGRAM_OBJS += index-helper.o > X = .exe > endif > ifeq ($(uname_S),Interix) > @@ -574,6 +575,7 @@ else > NO_CURL = YesPlease > endif > 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 4dd9656..cf26da7 100644 > --- a/index-helper.c > +++ b/index-helper.c > @@ -155,6 +155,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) > @@ -198,6 +243,9 @@ int main(int argc, char **argv) > fd = hold_lock_file_for_update(&lock, > git_path("index-helper.pid"), > LOCK_DIE_ON_ERROR); > +#ifdef GIT_WINDOWS_NATIVE > + strbuf_addstr(&sb, "HWND"); > +#endif > strbuf_addf(&sb, "%" 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 1a0ab0c..16fbdf6 100644 > --- a/read-cache.c > +++ b/read-cache.c > @@ -1546,6 +1546,18 @@ static void post_read_index_from(struct index_state *istate) > tweak_untracked_cache(istate); > } > > +#if defined(GIT_WINDOWS_NATIVE) > +static void do_poke(struct strbuf *sb, int refresh_cache) > +{ > + HWND hwnd; > + if (!starts_with(sb->buf, "HWND")) > + return; > + hwnd = FindWindow("git-index-helper", sb->buf); > + if (!hwnd) > + return; > + PostMessage(hwnd, refresh_cache ? WM_USER : WM_USER + 1, 0, 0); > +} > +#else > static void do_poke(struct strbuf *sb, int refresh_cache) > { > char *start = sb->buf; > @@ -1555,6 +1567,7 @@ static void do_poke(struct strbuf *sb, int refresh_cache) > return; > kill(pid, refresh_cache ? SIGHUP : SIGUSR1); > } > +#endif > > static void poke_daemon(struct index_state *istate, > const struct stat *st, int refresh_cache) > 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.4.2.767.g62658d5-twtrsrc > -- Duy -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html