void uwsgi_linux_ksm_map(void) {

	int dirty = 0;
	size_t i;
	unsigned long long start = 0, end = 0;
	int errors = 0;
	int lines = 0;

	int fd = open("/proc/self/maps", O_RDONLY);
	if (fd < 0) {
		uwsgi_error_open("[uwsgi-KSM] /proc/self/maps");
		return;
	}

	// allocate memory if not available;
	if (uwsgi.ksm_mappings_current == NULL) {
		if (!uwsgi.ksm_buffer_size)
			uwsgi.ksm_buffer_size = 32768;
		uwsgi.ksm_mappings_current = uwsgi_malloc(uwsgi.ksm_buffer_size);
		uwsgi.ksm_mappings_current_size = 0;
	}
	if (uwsgi.ksm_mappings_last == NULL) {
		if (!uwsgi.ksm_buffer_size)
			uwsgi.ksm_buffer_size = 32768;
		uwsgi.ksm_mappings_last = uwsgi_malloc(uwsgi.ksm_buffer_size);
		uwsgi.ksm_mappings_last_size = 0;
	}

	uwsgi.ksm_mappings_current_size = read(fd, uwsgi.ksm_mappings_current, uwsgi.ksm_buffer_size);
	close(fd);
	if (uwsgi.ksm_mappings_current_size <= 0) {
		uwsgi_log("[uwsgi-KSM] unable to read /proc/self/maps data\n");
		return;
	}

	// we now have areas
	if (uwsgi.ksm_mappings_last_size == 0 || uwsgi.ksm_mappings_current_size != uwsgi.ksm_mappings_last_size) {
		dirty = 1;
	}
	else {
		if (memcmp(uwsgi.ksm_mappings_current, uwsgi.ksm_mappings_last, uwsgi.ksm_mappings_current_size) != 0) {
			dirty = 1;
		}
	}

	// it is dirty, swap addresses and parse it
	if (dirty) {
		char *tmp = uwsgi.ksm_mappings_last;
		uwsgi.ksm_mappings_last = uwsgi.ksm_mappings_current;
		uwsgi.ksm_mappings_current = tmp;

		size_t tmp_size = uwsgi.ksm_mappings_last_size;
		uwsgi.ksm_mappings_last_size = uwsgi.ksm_mappings_current_size;
		uwsgi.ksm_mappings_current_size = tmp_size;

		// scan each line and call madvise on it
		char *ptr = uwsgi.ksm_mappings_last;
		for (i = 0; i < uwsgi.ksm_mappings_last_size; i++) {
			if (uwsgi.ksm_mappings_last[i] == '\n') {
				lines++;
				uwsgi.ksm_mappings_last[i] = 0;
				if (sscanf(ptr, "%llx-%llx %*s", &start, &end) == 2) {
					if (madvise((void *) (long) start, (size_t) (end - start), MADV_MERGEABLE)) {
						errors++;
					}
				}
				uwsgi.ksm_mappings_last[i] = '\n';
				ptr = uwsgi.ksm_mappings_last + i + 1;
			}
		}

		if (errors >= lines) {
			uwsgi_error("[uwsgi-KSM] unable to share pages");
		}
	}
}
void uwsgi_linux_ksm_map(void) {

	int dirty = 0;
	size_t i;
	unsigned long long start = 0, end = 0;
	int errors = 0;
	int lines = 0;

	int fd = open("/proc/self/maps", O_RDONLY);
	if (fd < 0) {
		uwsgi_error_open("[uwsgi-KSM] /proc/self/maps");
		return;
	}

	 
	if (uwsgi.ksm_mappings_current == NULL) {
		if (!uwsgi.ksm_buffer_size)
			uwsgi.ksm_buffer_size = 32768;
		uwsgi.ksm_mappings_current = uwsgi_malloc(uwsgi.ksm_buffer_size);
		uwsgi.ksm_mappings_current_size = 0;
	}
	if (uwsgi.ksm_mappings_last == NULL) {
		if (!uwsgi.ksm_buffer_size)
			uwsgi.ksm_buffer_size = 32768;
		uwsgi.ksm_mappings_last = uwsgi_malloc(uwsgi.ksm_buffer_size);
		uwsgi.ksm_mappings_last_size = 0;
	}

	uwsgi.ksm_mappings_current_size = read(fd, uwsgi.ksm_mappings_current, uwsgi.ksm_buffer_size);
	close(fd);
	if (uwsgi.ksm_mappings_current_size <= 0) {
		uwsgi_log("[uwsgi-KSM] unable to read /proc/self/maps data\n");
		return;
	}

	 
	if (uwsgi.ksm_mappings_last_size == 0 || uwsgi.ksm_mappings_current_size != uwsgi.ksm_mappings_last_size) {
		dirty = 1;
	}
	else {
		if (memcmp(uwsgi.ksm_mappings_current, uwsgi.ksm_mappings_last, uwsgi.ksm_mappings_current_size) != 0) {
			dirty = 1;
		}
	}

	 
	if (dirty) {
		char *tmp = uwsgi.ksm_mappings_last;
		uwsgi.ksm_mappings_last = uwsgi.ksm_mappings_current;
		uwsgi.ksm_mappings_current = tmp;

		size_t tmp_size = uwsgi.ksm_mappings_last_size;
		uwsgi.ksm_mappings_last_size = uwsgi.ksm_mappings_current_size;
		uwsgi.ksm_mappings_current_size = tmp_size;

		 
		char *ptr = uwsgi.ksm_mappings_last;
		for (i = 0; i < uwsgi.ksm_mappings_last_size; i++) {
			if (uwsgi.ksm_mappings_last[i] == '\n') {
				lines++;
				uwsgi.ksm_mappings_last[i] = 0;
				if (sscanf(ptr, "%llx-%llx %*s", &start, &end) == 2) {
					if (madvise((void *) (long) start, (size_t) (end - start), MADV_MERGEABLE)) {
						errors++;
					}
				}
				uwsgi.ksm_mappings_last[i] = '\n';
				ptr = uwsgi.ksm_mappings_last + i + 1;
			}
		}

		if (errors >= lines) {
			uwsgi_error("[uwsgi-KSM] unable to share pages");
		}
	}
}