4 * Miscellanious system support
21 RuneSysCall_bcopy(struct bcopy_args *args, void *rval __unused)
26 swrap = (uintptr_t)args->s.s_Addr + args->bytes;
27 dwrap = (uintptr_t)args->d.s_Addr + args->bytes;
28 if (args->bytes > 0) {
29 dassert(args->s.s_Addr >= args->s.s_Beg &&
30 swrap <= (uintptr_t)args->s.s_End &&
31 swrap >= (uintptr_t)args->s.s_Addr &&
32 args->d.s_Addr >= args->d.s_Beg &&
33 dwrap <= (uintptr_t)args->d.s_End &&
34 dwrap >= (uintptr_t)args->d.s_Addr);
35 bcopy(args->s.s_Addr, args->d.s_Addr, args->bytes);
37 refprintf("args %jd\n", args->bytes);
38 dassert(args->bytes == 0);
47 static void donew(struct new_args *args, int islocked);
50 RuneSysCall_new_locked(struct new_args *args, void *rval __unused)
56 RuneSysCall_new_unlocked(struct new_args *args, void *rval __unused)
64 donew(struct new_args *args, int islocked)
66 runesize_t count = args->count;
68 Type *ptype = args->lvs.s_Type;
75 refprintf("NEW args=%p ptype=%p %jd\n", args, ptype, ptype->ty_Bytes);
76 refprintf("NEWLVS %p %p %p\n", args->lvs.s_Addr, args->lvs.s_RefStor, args->lvs.s_Type);
79 switch(ptype->ty_Op) {
83 * Use the type in the pointer (even if the pointer is NULL
84 * it should be properly typed). This is the object target
87 * XXX Allow the case where the pointer is completely zerod
88 * and take the reftype for that case ?
90 ps = (void *)args->lvs.s_Addr;
92 dassert(type != NULL);
94 refprintf("NEWLVS-PTR %p %p %p %p %p\n", ps->s_Addr, ps->s_Beg, ps->s_End, ps->s_RefStor, ps->s_Type);
98 * Must use ptype to determine whether the storage
101 refprintf("NEW: Putaway old RS=%p (assume locked storage)", ps->s_RefStor);
103 RuneRunTime_RSPut(ps->s_RefStor);
105 RuneRunTime_RSRel(ps->s_RefStor);
107 ps->s_RefStor = NULL;
112 dpanic("Rune new() called on non-pointer/non-reference ty=%d",
116 bytes = type->ty_Bytes * count;
118 dassert(bytes / count == type->ty_Bytes);
120 if (type->ty_SQFlags & SF_NOZERO &&
121 (type->ty_Flags & TF_HASLVPTR) == 0) {
122 base = znalloc(bytes);
124 base = zalloc(bytes);
128 ps->s_End = base + bytes;
129 ps->s_RefStor = NULL;
132 rs = allocRefStor(type, RSOP_ZALLOC);
133 rs->rs_Count = count;
138 RuneRunTime_RSLock(rs);
142 * Call run-time function to initialize the type if it needs it.
144 if (type->ty_Flags & (TF_HASLVPTR | TF_HASASS | TF_HASCONSTRUCT)) {
146 ((itype_func_t)type->ty_DynamicVector[0])(base, type);
148 base += type->ty_Bytes;
154 * Run-time heap and persistent store allocator. This function will
155 * completely initialize a LValueStor given a storage declaration. We
156 * need the decl and not just the type in order to determine whether the
157 * LValue represents HEAP or PERSISTent storage.
159 * Target storage is typically global so we assume unlocked semantics.
160 * Caller will lock the storage upon return if needed.
163 RuneRunTime_LVAlloc(LValueStor *lvs, Declaration *d)
165 Type *type = d->d_StorDecl.ed_Type;
169 if (d->d_ScopeFlags & SCOPE_HEAP) {
170 rs = allocRefStor(type, RSOP_ZALLOC);
172 if ((type->ty_SQFlags & SF_NOZERO) &&
173 (type->ty_Flags & TF_HASLVPTR) == 0) {
174 rs->rs_Base = znalloc(type->ty_Bytes);
176 rs->rs_Base = zalloc(type->ty_Bytes);
179 fprintf(stderr, "LVAlloc: %jd (heap) rs=%p b=%p\n", type->ty_Bytes, rs, rs->rs_Base);
181 } else if (d->d_ScopeFlags & SCOPE_PERSIST) {
192 fprintf(stderr, "LVAlloc: %s - %jd (persist)\n",
197 * Default path is "$RUNEDATA/$prog/rune_%s.map".
199 * $prog is set to the project directive. If there is no
200 * project directive $prog is set to the base program name.
202 * If RUNEDATA exists we use $RUNEDATA/$prog/rune_*.map
203 * else if uid == 0 we use /var/rune/$prog/rune_*.map
204 * else if HOME we use $HOME/.rune/$prog/rune_*.map
205 * else if USER we use /tmp/$USER/$prog/rune_*.map
206 * else we use /tmp/$prog/rune_*.map
210 if (d->d_ScopeFlags & SCOPE_SHARED) {
211 SemGroup *sg = d->d_MyGroup;
214 while (prog == NULL && sg) {
215 prog = sg->sg_Project;
221 prog = getprogname();
223 if (strrchr(prog, '/'))
224 prog = strrchr(prog, '/');
225 if (strrchr(prog, '.'))
226 plen = strrchr(prog, '.') - prog;
228 plen = (int)strlen(prog);
229 if (plen > 2 && prog[plen-2] == '.')
232 base = getenv("RUNEDATA");
234 asprintf(&path, "%s/%*.*s/rune_%s.map",
235 base, plen, plen, prog, id);
236 } else if (getuid() == 0) {
237 asprintf(&path, "/var/rune/%*.*s/rune_%s.map",
238 plen, plen, prog, id);
239 } else if ((base = getenv("HOME")) != NULL) {
240 asprintf(&path, "%s/.rune/%*.*s/rune_%s.map",
241 base, plen, plen, prog, id);
242 } else if ((base = getenv("USER")) != NULL) {
243 asprintf(&path, "/tmp/%s/%*.*s/rune_%s.map",
244 base, plen, plen, prog, id);
246 asprintf(&path, "/tmp/%*.*s/rune_%s.map",
247 plen, plen, prog, id);
249 fprintf(stderr, "PATH %s\n", path);
250 fd = open(path, O_RDWR|O_CREAT, 0666);
253 fd = open(path, O_RDWR|O_CREAT, 0666);
255 fprintf(stderr, "Cannot open/create \"%s\"\n",
261 if (st.st_size == RSRESERVE + (off_t)type->ty_Bytes)
263 ftruncate(fd, RSRESERVE + type->ty_Bytes);
264 dassert(RSRESERVE >= sizeof(*rs));
265 rs = zalloc(sizeof(*rs));
266 rs->rs_Base = mmap(NULL, RSRESERVE + type->ty_Bytes,
267 PROT_READ|PROT_WRITE,
268 MAP_SHARED|MAP_NOCORE|MAP_NOSYNC,
270 if ((void *)rs->rs_Base == MAP_FAILED)
271 dpanic("persist storage mmap(\"%s\") failed\n", path);
272 initRefStor(rs, type, RSOP_PERSIST);
273 rs->rs_Base += RSRESERVE;
276 bzero(rs->rs_Base, type->ty_Bytes);
280 dpanic("Unsupported scope for lvalue declaration, "
281 "(requires 'heap' or 'persist' only)");
284 /* assumes unlocked semantics */
285 /*RuneRunTime_RSLock(rs);*/
287 lvs->s_Addr = rs->rs_Base;
292 * Call run-time function to initialize the type if it needs it.
294 * XXX if already initialized we still want to call the constructors.
296 if (type->ty_Flags & (TF_HASLVPTR | TF_HASASS | TF_HASCONSTRUCT)) {
299 type->ty_DynamicVector[0])(lvs->s_Addr, type);
311 RuneSysCall_exit(struct exit_args *args, void *rval __unused)
322 RuneSysCall_abort(struct abort_args *args __unused, void *rval __unused)
333 RuneSysCall_getenv(struct getenv_args *args, PointerStor *resp)
340 if ((rs = resp->s_RefStor) != NULL) {
341 RuneRunTime_RSRel(rs);
345 resp->s_RefStor = NULL;
347 STRBOUNDSCHECK(&args->name, PATH_MAX);
348 str = getenv(args->name.s_Addr);
350 len = strlen(str) + 1;
352 bcopy(str, base, len);
353 rs = allocRefStor(&CharPtrType, RSOP_ZALLOC);
356 rs->rs_Type = &UInt8Type;
360 resp->s_End = base + len;
361 resp->s_RefStor = rs;
362 resp->s_Type = &CharPtrType;
373 RuneSysCall_setenv(struct setenv_args *args, void *resp)
375 STRBOUNDSCHECK(&args->name, 0x3FFFFFFF);
376 STRBOUNDSCHECK(&args->value, 0x3FFFFFFF);
377 if (setenv(args->name.s_Addr, args->value.s_Addr, 1) < 0) {
378 dpanic("setenv(\"%s\", \"%s\") failed",
379 args->name.s_Addr, args->value.s_Addr);
383 struct unsetenv_args {
388 RuneSysCall_unsetenv(struct unsetenv_args *args, int *resp)
390 STRBOUNDSCHECK(&args->name, PATH_MAX);
391 if (unsetenv(args->name.s_Addr) < 0) {