dr_util.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include <sys/cmn_err.h>
#include <sys/param.h> /* for NULL */
#include <sys/sbd_ioctl.h>
#include <sys/dr_util.h>
#include <sys/varargs.h>
#include <sys/sysmacros.h>
#include <sys/systm.h>
/* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */
extern sbd_etab_t sbd_etab[];
extern int sbd_etab_len;
sbd_error_t *
sbd_err_new(int e_code, char *fmt, va_list args)
{
sbd_error_t *new;
new = GETSTRUCT(sbd_error_t, 1);
new->e_code = e_code;
if (fmt)
(void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args);
return (new);
}
void
sbd_err_log(sbd_error_t *ep, int ce)
{
char buf[32];
char *fmt;
char *txt;
int i;
sbd_etab_t *tp;
if (!ep)
return;
if (ep->e_rsc[0] == '\0')
fmt = "%s";
else
fmt = "%s: %s";
for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++)
if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd)
break;
if (i < sbd_etab_len)
txt = tp->t_text[ep->e_code - tp->t_base];
else {
snprintf(buf, sizeof (buf), "error %d", ep->e_code);
txt = buf;
}
cmn_err(ce, fmt, txt, ep->e_rsc);
}
void
sbd_err_clear(sbd_error_t **ep)
{
FREESTRUCT(*ep, sbd_error_t, 1);
*ep = NULL;
}
void
sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
{
sbd_error_t *tmp;
va_list args;
va_start(args, fmt);
tmp = sbd_err_new(e_code, fmt, args);
sbd_err_log(tmp, ce);
if (*ep == NULL)
*ep = tmp;
else
sbd_err_clear(&tmp);
va_end(args);
}
void
sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
{
sbd_error_t *tmp;
va_list args;
va_start(args, fmt);
tmp = sbd_err_new(e_code, fmt, args);
sbd_err_log(tmp, ce);
*ep = tmp;
va_end(args);
}
sbd_error_t *
drerr_new_v(int e_code, char *fmt, va_list args)
{
return (sbd_err_new(e_code, fmt, args));
}
sbd_error_t *
drerr_new(int log, int e_code, char *fmt, ...)
{
sbd_error_t *ep;
va_list args;
va_start(args, fmt);
ep = sbd_err_new(e_code, fmt, args);
va_end(args);
if (log)
sbd_err_log(ep, CE_WARN);
return (ep);
}
void
drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...)
{
sbd_error_t *err;
va_list args;
va_start(args, fmt);
err = sbd_err_new(e_code, fmt, args);
va_end(args);
if (log)
sbd_err_log(err, CE_WARN);
if (*ep == NULL)
*ep = err;
else
sbd_err_clear(&err);
}
/*
* Memlist support.
*/
void
memlist_delete(struct memlist *mlist)
{
register struct memlist *ml;
for (ml = mlist; ml; ml = mlist) {
mlist = ml->next;
FREESTRUCT(ml, struct memlist, 1);
}
}
int
memlist_intersect(struct memlist *al, struct memlist *bl)
{
uint64_t astart, aend, bstart, bend;
if ((al == NULL) || (bl == NULL))
return (0);
aend = al->address + al->size;
bstart = bl->address;
bend = bl->address + bl->size;
while (al && bl) {
while (al && (aend <= bstart))
if ((al = al->next) != NULL)
aend = al->address + al->size;
if (al == NULL)
return (0);
if ((astart = al->address) <= bstart)
return (1);
while (bl && (bend <= astart))
if ((bl = bl->next) != NULL)
bend = bl->address + bl->size;
if (bl == NULL)
return (0);
if ((bstart = bl->address) <= astart)
return (1);
}
return (0);
}
void
memlist_coalesce(struct memlist *mlist)
{
uint64_t end, nend;
if ((mlist == NULL) || (mlist->next == NULL))
return;
while (mlist->next) {
end = mlist->address + mlist->size;
if (mlist->next->address <= end) {
struct memlist *nl;
nend = mlist->next->address + mlist->next->size;
if (nend > end)
mlist->size += (nend - end);
nl = mlist->next;
mlist->next = mlist->next->next;
if (nl) {
FREESTRUCT(nl, struct memlist, 1);
}
if (mlist->next)
mlist->next->prev = mlist;
} else {
mlist = mlist->next;
}
}
}
#ifdef DEBUG
void
memlist_dump(struct memlist *mlist)
{
register struct memlist *ml;
if (mlist == NULL)
printf("memlist> EMPTY\n");
else for (ml = mlist; ml; ml = ml->next)
printf("memlist> 0x%llx, 0x%llx\n", ml->address, ml->size);
}
#endif