Commit e11ab7f4 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add mark/clean facility to VSM, so that all dynamic allocations gets

Freeed (cooled) on child start.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@4965 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 02923e29
......@@ -341,18 +341,18 @@ pan_ic(const char *func, const char *file, int line, const char *cond,
vsb_bcat(vsp, "", 1); /* NUL termination */
if (params->diag_bitmap & 0x4000)
(void)fputs(loghead->panicstr, stderr);
(void)fputs(vsm_head->panicstr, stderr);
#ifdef HAVE_ABORT2
if (params->diag_bitmap & 0x8000) {
void *arg[1];
char *p;
for (p = loghead->panicstr; *p; p++)
for (p = vsm_head->panicstr; *p; p++)
if (*p == '\n')
*p = ' ';
arg[0] = loghead->panicstr;
abort2(loghead->panicstr, 1, arg);
arg[0] = vsm_head->panicstr;
abort2(vsm_head->panicstr, 1, arg);
}
#endif
if (params->diag_bitmap & 0x1000)
......@@ -369,6 +369,6 @@ PAN_Init(void)
vas_fail = pan_ic;
vsp = &vsps;
AN(vsb_new(vsp, loghead->panicstr, sizeof loghead->panicstr,
AN(vsb_new(vsp, vsm_head->panicstr, sizeof vsm_head->panicstr,
VSB_FIXEDLEN));
}
......@@ -43,7 +43,7 @@ SVNID("$Id$")
static pthread_mutex_t vsl_mtx;
static uint32_t *vsl_start;
static uint32_t *vsl_end;
static const uint32_t *vsl_end;
static uint32_t *vsl_ptr;
static inline uint32_t
......@@ -276,6 +276,8 @@ VSL_Init(void)
AZ(pthread_mutex_init(&vsl_mtx, NULL));
VSM_Clean();
VSM_ITER(vsc)
if (!strcmp(vsc->class, VSL_CLASS))
break;
......@@ -285,8 +287,8 @@ VSL_Init(void)
vsl_ptr = vsl_start + 1;
vsl_wrap();
loghead->starttime = (intmax_t)TIM_real();
loghead->panicstr[0] = '\0';
vsm_head->starttime = (intmax_t)TIM_real();
vsm_head->panicstr[0] = '\0';
memset(VSL_stats, 0, sizeof *VSL_stats);
loghead->child_pid = getpid();
vsm_head->child_pid = getpid();
}
......@@ -71,12 +71,22 @@ const void *pick(const struct choice *cp, const char *which, const char *kind);
/* vsm.c */
extern struct vsm_head *vsm_head;
extern void *vsm_end;
extern const struct vsm_chunk *vsm_end;
void *VSM_Alloc(unsigned size, const char *class, const char *type,
const char *ident);
void VSM_Free(const void *ptr);
void VSM_Clean(void);
struct vsm_chunk *vsm_iter_0(void);
void vsm_iter_n(struct vsm_chunk **pp);
#define VSM_ITER(vd) for ((vd) = vsm_iter_0(); (vd) != NULL; vsm_iter_n(&vd))
/* These classes are opaque to other programs, so we define the here */
#define VSM_CLASS_FREE "Free"
#define VSM_CLASS_COOL "Cool"
#define VSM_CLASS_PARAM "Params"
#define VSM_CLASS_MARK "MgrCld"
#define VSM_COOL_TIME 5
......@@ -461,10 +461,10 @@ static void
mgt_report_panic(pid_t r)
{
if (loghead->panicstr[0] == '\0')
if (vsm_head->panicstr[0] == '\0')
return;
REPORT(LOG_ERR, "Child (%jd) Panic message: %s",
(intmax_t)r, loghead->panicstr);
(intmax_t)r, vsm_head->panicstr);
}
/*--------------------------------------------------------------------*/
......
......@@ -114,7 +114,6 @@ SVNID("$Id$")
#endif
struct vsc_main *VSL_stats;
struct vsm_head *loghead;
static int vsl_fd = -1;
......@@ -272,29 +271,28 @@ mgt_SHM_Init(const char *l_arg)
(void)close(i);
vsl_buildnew(VSM_FILENAME, size, fill);
loghead = (void *)mmap(NULL, size,
vsm_head = (void *)mmap(NULL, size,
PROT_READ|PROT_WRITE,
MAP_HASSEMAPHORE | MAP_NOSYNC | MAP_SHARED,
vsl_fd, 0);
loghead->master_pid = getpid();
xxxassert(loghead != MAP_FAILED);
(void)mlock((void*)loghead, size);
memset(&loghead->head, 0, sizeof loghead->head);
loghead->head.magic = VSM_CHUNK_MAGIC;
loghead->head.len =
(uint8_t*)(loghead) + size - (uint8_t*)&loghead->head;
bprintf(loghead->head.class, "%s", "Free");
vsm_head->master_pid = getpid();
xxxassert(vsm_head != MAP_FAILED);
(void)mlock((void*)vsm_head, size);
memset(&vsm_head->head, 0, sizeof vsm_head->head);
vsm_head->head.magic = VSM_CHUNK_MAGIC;
vsm_head->head.len =
(uint8_t*)(vsm_head) + size - (uint8_t*)&vsm_head->head;
bprintf(vsm_head->head.class, "%s", VSM_CLASS_FREE);
VWMB();
vsm_head = loghead;
vsm_end = (uint8_t*)loghead + size;
vsm_end = (void*)((uint8_t*)vsm_head + size);
VSL_stats = VSM_Alloc(sizeof *VSL_stats,
VSC_CLASS, VSC_TYPE_MAIN, "");
AN(VSL_stats);
pp = VSM_Alloc(sizeof *pp, "Params", "", "");
pp = VSM_Alloc(sizeof *pp, VSM_CLASS_PARAM, "", "");
AN(pp);
*pp = *params;
params = pp;
......@@ -311,8 +309,8 @@ mgt_SHM_Init(const char *l_arg)
VWMB();
do
loghead->alloc_seq = random();
while (loghead->alloc_seq == 0);
vsm_head->alloc_seq = random();
while (vsm_head->alloc_seq == 0);
}
......@@ -320,5 +318,5 @@ void
mgt_SHM_Pid(void)
{
loghead->master_pid = getpid();
vsm_head->master_pid = getpid();
}
......@@ -631,6 +631,8 @@ main(int argc, char * const *argv)
if (T_arg != NULL)
mgt_cli_telnet(T_arg);
VSM_Alloc(0, VSM_CLASS_MARK, "", "");
MGT_Run();
if (pfh != NULL)
......
......@@ -45,7 +45,30 @@ SVNID("$Id$")
#include "vmb.h"
struct vsm_head *vsm_head;
void *vsm_end;
const struct vsm_chunk *vsm_end;
static unsigned
vsm_mark(void)
{
unsigned seq;
seq = vsm_head->alloc_seq;
vsm_head->alloc_seq = 0;
VWMB();
return (seq);
}
static void
vsm_release(unsigned seq)
{
if (seq == 0)
return;
VWMB();
do
vsm_head->alloc_seq = ++seq;
while (vsm_head->alloc_seq == 0);
}
/*--------------------------------------------------------------------*/
......@@ -65,7 +88,7 @@ vsm_iter_n(struct vsm_chunk **pp)
CHECK_OBJ_NOTNULL(vsm_head, VSM_HEAD_MAGIC);
CHECK_OBJ_NOTNULL(*pp, VSM_CHUNK_MAGIC);
*pp = VSM_NEXT(*pp);
if ((void*)(*pp) >= vsm_end) {
if (*pp >= vsm_end) {
*pp = NULL;
return;
}
......@@ -74,6 +97,63 @@ vsm_iter_n(struct vsm_chunk **pp)
/*--------------------------------------------------------------------*/
static void
vsm_cleanup(void)
{
unsigned now = (unsigned)TIM_mono();
struct vsm_chunk *sha, *sha2;
unsigned seq;
CHECK_OBJ_NOTNULL(vsm_head, VSM_HEAD_MAGIC);
VSM_ITER(sha) {
if (strcmp(sha->class, VSM_CLASS_COOL))
continue;
if (sha->state + VSM_COOL_TIME < now)
break;
}
if (sha == NULL)
return;
seq = vsm_mark();
/* First pass, free, and collaps with next if applicable */
VSM_ITER(sha) {
if (strcmp(sha->class, VSM_CLASS_COOL))
continue;
if (sha->state + VSM_COOL_TIME >= now)
continue;
bprintf(sha->class, "%s", VSM_CLASS_FREE);
bprintf(sha->type, "%s", "");
bprintf(sha->ident, "%s", "");
sha2 = VSM_NEXT(sha);
assert(sha2 <= vsm_end);
if (sha2 == vsm_end)
break;
CHECK_OBJ_NOTNULL(sha2, VSM_CHUNK_MAGIC);
if (!strcmp(sha2->class, VSM_CLASS_FREE)) {
sha->len += sha2->len;
memset(sha2, 0, sizeof *sha2);
}
sha->state = 0;
}
/* Second pass, collaps with prev if applicable */
VSM_ITER(sha) {
if (strcmp(sha->class, VSM_CLASS_FREE))
continue;
sha2 = VSM_NEXT(sha);
assert(sha2 <= vsm_end);
if (sha2 == vsm_end)
break;
CHECK_OBJ_NOTNULL(sha2, VSM_CHUNK_MAGIC);
if (!strcmp(sha2->class, VSM_CLASS_FREE)) {
sha->len += sha2->len;
memset(sha2, 0, sizeof *sha2);
}
}
vsm_release(seq);
}
/*--------------------------------------------------------------------*/
void *
VSM_Alloc(unsigned size, const char *class, const char *type, const char *ident)
{
......@@ -82,6 +162,8 @@ VSM_Alloc(unsigned size, const char *class, const char *type, const char *ident)
CHECK_OBJ_NOTNULL(vsm_head, VSM_HEAD_MAGIC);
vsm_cleanup();
/* Round up to pointersize */
size += sizeof(void *) - 1;
size &= ~(sizeof(void *) - 1);
......@@ -91,35 +173,77 @@ VSM_Alloc(unsigned size, const char *class, const char *type, const char *ident)
VSM_ITER(sha) {
CHECK_OBJ_NOTNULL(sha, VSM_CHUNK_MAGIC);
if (strcmp(sha->class, "Free"))
if (strcmp(sha->class, VSM_CLASS_FREE))
continue;
xxxassert(size <= sha->len);
if (size > sha->len)
continue;
sha2 = (void*)((uintptr_t)sha + size);
/* Mark as inconsistent while we write string fields */
seq = vsm_mark();
/* Mark as inconsistent while we write string fields */
seq = vsm_head->alloc_seq;
vsm_head->alloc_seq = 0;
VWMB();
if (size < sha->len) {
sha2 = (void*)((uintptr_t)sha + size);
memset(sha2, 0, sizeof *sha2);
sha2->magic = VSM_CHUNK_MAGIC;
sha2->len = sha->len - size;
bprintf(sha2->class, "%s", "Free");
memset(sha2, 0, sizeof *sha2);
sha2->magic = VSM_CHUNK_MAGIC;
sha2->len = sha->len - size;
bprintf(sha2->class, "%s", VSM_CLASS_FREE);
sha->len = size;
}
sha->len = size;
bprintf(sha->class, "%s", class);
bprintf(sha->type, "%s", type);
bprintf(sha->ident, "%s", ident);
VWMB();
if (seq != 0)
do
loghead->alloc_seq = ++seq;
while (loghead->alloc_seq == 0);
vsm_release(seq);
return (VSM_PTR(sha));
}
return (NULL);
}
/*--------------------------------------------------------------------*/
void
VSM_Free(const void *ptr)
{
struct vsm_chunk *sha;
unsigned seq;
CHECK_OBJ_NOTNULL(vsm_head, VSM_HEAD_MAGIC);
VSM_ITER(sha)
if (VSM_PTR(sha) == ptr)
break;
AN(sha);
seq = vsm_mark();
bprintf(sha->class, "%s", VSM_CLASS_COOL);
sha->state = (unsigned)TIM_mono();
vsm_release(seq);
}
/*--------------------------------------------------------------------
* Free all allocations after the mark (ie: allocated by child).
*/
void
VSM_Clean(void)
{
struct vsm_chunk *sha;
unsigned f, seq;
CHECK_OBJ_NOTNULL(vsm_head, VSM_HEAD_MAGIC);
f = 0;
seq = vsm_mark();
VSM_ITER(sha) {
if (f == 0 && !strcmp(sha->class, VSM_CLASS_MARK)) {
f = 1;
continue;
}
if (f == 0)
continue;
if (strcmp(sha->class, VSM_CLASS_FREE) &&
strcmp(sha->class, VSM_CLASS_COOL))
VSM_Free(VSM_PTR(sha));
}
vsm_release(seq);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment