catch up to latest http2 interface

catch up to latest http2 interface

--- lib/common/http2client.c
+++ lib/common/http2client.c
@@ -44,13 +44,8 @@
     CONN_STATE_IS_CLOSING,
 };

-static const h2o_http2_settings_t H2O_HTTP2_SETTINGS_CLIENT = {
-    4096,     /* header_table_size */
-    0,        /* enable_push (http2client doesn't support push) */
-    100,      /* max_concurrent_streams */
-    16777216, /* initial_window_size */
-    16384     /* max_frame_size */
-};
+#define H2O_HTTP2_SETTINGS_CLIENT_INITIAL_WINDOW_SIZE 16777216
+#define H2O_HTTP2_SETTINGS_CLIENT_HEADER_TABLE_SIZE 4096

 #define H2O_HTTP2_DEFAULT_OUTBUF_SIZE 81920
 static __thread h2o_buffer_prototype_t wbuf_buffer_prototype = {{16}, {H2O_HTTP2_DEFAULT_OUTBUF_SIZE}};
@@ -163,8 +158,8 @@
 static void update_input_window(struct st_h2o_http2client_conn_t *conn, uint32_t stream_id, h2o_http2_window_t *window, size_t consumed)
 {
     h2o_http2_window_consume_window(window, consumed);
-    if (h2o_http2_window_get_window(window) * 2 < H2O_HTTP2_SETTINGS_CLIENT.initial_window_size) {
-        int32_t delta = (int32_t)(H2O_HTTP2_SETTINGS_CLIENT.initial_window_size - h2o_http2_window_get_window(window));
+    if (h2o_http2_window_get_avail(window) * 2 < H2O_HTTP2_SETTINGS_CLIENT_INITIAL_WINDOW_SIZE) {
+        int32_t delta = (int32_t)(H2O_HTTP2_SETTINGS_CLIENT_INITIAL_WINDOW_SIZE - h2o_http2_window_get_avail(window));
         h2o_http2_encode_window_update_frame(&conn->output.buf, stream_id, delta);
         request_write(conn);
         h2o_http2_window_update(window, delta);
@@ -312,7 +307,7 @@
     struct st_h2o_http2client_stream_t *stream;
     int hret;

-    if ((ret = h2o_http2_decode_frame(&frame, src, len, &H2O_HTTP2_SETTINGS_CLIENT, err_desc)) < 0)
+    if ((ret = h2o_http2_decode_frame(&frame, src, len, err_desc)) < 0)
         return ret;
     if (frame.type != H2O_HTTP2_FRAME_TYPE_CONTINUATION) {
         *err_desc = "expected CONTINUATION frame";
@@ -499,10 +494,10 @@

 static int update_stream_output_window(struct st_h2o_http2client_stream_t *stream, ssize_t delta)
 {
-    ssize_t before = h2o_http2_window_get_window(&stream->output.window);
+    ssize_t before = h2o_http2_window_get_avail(&stream->output.window);
     if (h2o_http2_window_update(&stream->output.window, delta) != 0)
         return -1;
-    ssize_t after = h2o_http2_window_get_window(&stream->output.window);
+    ssize_t after = h2o_http2_window_get_avail(&stream->output.window);
     if (before <= 0 && 0 < after && stream->output.data.size != 0) {
         assert(!h2o_linklist_is_linked(&stream->output.sending_link));
         h2o_linklist_insert(&stream->conn->output.sending_streams, &stream->output.sending_link);
@@ -526,7 +521,7 @@
     if (ret < H2O_HTTP2_FRAME_HEADER_SIZE)
         return 0;
     ret -= H2O_HTTP2_FRAME_HEADER_SIZE;
-    winsz = h2o_http2_window_get_window(&conn->output.window);
+    winsz = h2o_http2_window_get_avail(&conn->output.window);
     if (winsz < ret)
         ret = winsz;
     return ret;
@@ -680,7 +675,7 @@
         handle_invalid_continuation_frame /* CONTINUATION */
     };

-    if ((ret = h2o_http2_decode_frame(&frame, src, len, &H2O_HTTP2_SETTINGS_CLIENT, err_desc)) < 0)
+    if ((ret = h2o_http2_decode_frame(&frame, src, len, err_desc)) < 0)
         return ret;

     if (frame.type < sizeof(FRAME_HANDLERS) / sizeof(FRAME_HANDLERS[0])) {
@@ -701,7 +696,7 @@
     h2o_http2_frame_t frame;
     ssize_t ret;

-    if ((ret = h2o_http2_decode_frame(&frame, src, len, &H2O_HTTP2_SETTINGS_CLIENT, err_desc)) < 0)
+    if ((ret = h2o_http2_decode_frame(&frame, src, len, err_desc)) < 0)
         return ret;

     if (frame.type != H2O_HTTP2_FRAME_TYPE_SETTINGS)
@@ -905,7 +900,7 @@

     register_stream(stream, conn);

-    h2o_http2_window_init(&stream->output.window, &conn->peer_settings);
+    h2o_http2_window_init(&stream->output.window, conn->peer_settings.initial_window_size);

     /* send headers */
     h2o_headers_t headers_vec = {headers, num_headers, num_headers};
@@ -996,7 +991,7 @@

     if ((conn_max = conn_get_buffer_window(stream->conn)) <= 0)
         return 0;
-    if ((stream_max = h2o_http2_window_get_window(&stream->output.window)) <= 0)
+    if ((stream_max = h2o_http2_window_get_avail(&stream->output.window)) <= 0)
         return 0;
     return sz_min(sz_min(conn_max, stream_max), stream->conn->peer_settings.max_frame_size);
 }
@@ -1073,7 +1068,7 @@

         if (stream->output.data.size == 0) {
             h2o_linklist_insert(&conn->output.sent_streams, node);
-        } else if (h2o_http2_window_get_window(&stream->output.window) > 0) {
+        } else if (h2o_http2_window_get_avail(&stream->output.window) > 0) {
             h2o_linklist_insert(&conn->output.sending_streams, node); /* move to the tail to rotate buffers */
         }

@@ -1153,8 +1148,8 @@
     conn->keepalive_timeout_entry.cb = on_keepalive_timeout;

     /* output */
-    conn->output.header_table.hpack_capacity = H2O_HTTP2_SETTINGS_CLIENT.header_table_size;
-    h2o_http2_window_init(&conn->output.window, &conn->peer_settings);
+    conn->output.header_table.hpack_capacity = H2O_HTTP2_SETTINGS_CLIENT_HEADER_TABLE_SIZE;
+    h2o_http2_window_init(&conn->output.window, conn->peer_settings.initial_window_size);
     h2o_buffer_init(&conn->output.buf, &wbuf_buffer_prototype);
     conn->output.defer_timeout_entry.cb = emit_writereq;
     h2o_linklist_init_anchor(&conn->output.sending_streams);
@@ -1163,7 +1158,7 @@
     /* input */
     conn->input.header_table.hpack_capacity = conn->input.header_table.hpack_max_capacity =
     H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
-    h2o_http2_window_init(&conn->input.window, &H2O_HTTP2_SETTINGS_DEFAULT);
+    h2o_http2_window_init(&conn->input.window, H2O_HTTP2_SETTINGS_DEFAULT.initial_window_size);
     conn->input.read_frame = expect_settings;

     return conn;
@@ -1214,7 +1209,7 @@
     stream->input.res.content_length = SIZE_MAX;
     stream->state = STREAM_STATE_SEND_HEADERS;
     stream->timeout_entry.cb = on_stream_timeout;
-    h2o_http2_window_init(&stream->input.window, &H2O_HTTP2_SETTINGS_CLIENT);
+    h2o_http2_window_init(&stream->input.window, H2O_HTTP2_SETTINGS_CLIENT_INITIAL_WINDOW_SIZE);

     /* caller needs to setup _cb, timeout.cb, sock, and sock->data */


isc_log_write called with extra parameter, typos

--- lib/dns/config/confndc.c
+++ lib/dns/config/confndc.c
@@ -15,7 +15,7 @@
  * SOFTWARE.
  */

-/* $Id: confndc.c,v 1.17 2000/06/02 15:12:28 brister Exp $ */
+/* $Id: confndc.c,v 1.18 2000/06/19 17:41:42 bwelling Exp $ */

 /*
 **	options {
@@ -1421,7 +1421,7 @@
         }

 	/*
-	 * 97 == buckey size: higest prime < 100
+	 * 97 == bucket size: highest prime < 100
 	 */
 	result = isc_symtab_create(mem, 97, NULL, NULL, ISC_FALSE,
 				   &pctx->thekeywords);
@@ -1429,7 +1429,7 @@
                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG,
                               DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL,
                               "%s: Error creating symtab",
-                              "dns_c_parse_namedconf", filename);
+                              "dns_c_parse_namedconf");
 		return (result);
 	}


vp9 svc: Update temporal_layering_mode in config change.

temporal_layering_mode can be changed on the fly.

BUG=webm:1488

Change-Id: I223fd4085184e41878ddf0f9244d2e3d07636ae3

--- vp9/encoder/vp9_svc_layercontext.c
+++ vp9/encoder/vp9_svc_layercontext.c
@@ -154,6 +154,8 @@
   const RATE_CONTROL *const rc = &cpi->rc;
   int sl, tl, layer = 0, spatial_layer_target;
   float bitrate_alloc = 1.0;
+
+  cpi->svc.temporal_layering_mode = oxcf->temporal_layering_mode;

   if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING) {
     for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {


6c bug with large constants

6c bug with large constants

R=r
OCL=19056
CL=19056

--- src/cmd/6c/txt.c
+++ src/cmd/6c/txt.c
@@ -642,6 +642,17 @@
 /*
  * load
  */
+	if(ft == TVLONG || ft == TUVLONG)
+	if(f->op == OCONST)
+	if(f->vconst > 0x7fffffffLL || f->vconst < -0x7fffffffLL)
+	if(t->op != OREGISTER) {
+		regalloc(&nod, f, Z);
+		gmove(f, &nod);
+		gmove(&nod, t);
+		regfree(&nod);
+		return;
+	}
+
 	if(f->op == ONAME || f->op == OINDREG ||
 	   f->op == OIND || f->op == OINDEX)
 	switch(ft) {


remove unnecessary ifdef

remove unnecessary ifdef

--- rts/RtsStartup.c
+++ rts/RtsStartup.c
@@ -435,10 +435,8 @@
     // Free the various argvs
     freeRtsArgs();

-#ifndef CMINUSMINUS
     // Free threading resources
     freeThreadingResources();
-#endif
 }

 // Flush stdout and stderr.  We do this during shutdown so that it


backend work

backend work

--- src/cmd/c/emit.c
+++ src/cmd/c/emit.c
@@ -55,7 +55,28 @@
 		out("movsbq (%%rax), %%rax\n");
 		break;
 	default:
-		errorf("unimplemented emitloadreg\n");
+		errorf("internal error emitloadreg\n");
+	}
+}
+
+static void
+emitstorereg(int sz)
+{
+	switch(sz) {
+	case 8:
+		out("movq %%rbx, (%%rax)\n");
+		break;
+	case 4:
+		out("movl %%ebx, (%%rax)\n");
+		break;
+	case 2:
+		out("movw %%bx, (%%rax)\n");
+		break;
+	case 1:
+		out("movb %%bl, (%%rax)\n");
+		break;
+	default:
+		errorf("internal emitstorereg\n");
 	}
 }

@@ -81,7 +102,7 @@
 		out("pushq %%rbx\n");
 		emitexpr(l->Unop.operand);
 		out("popq %%rbx\n");
-		out("movq %%rbx, (%%rax)\n");
+		emitstorereg(8);
 		break;
 	case NIDENT:
 		sym = l->Ident.sym;
@@ -89,11 +110,11 @@
 		case SCSTATIC:
 		case SCGLOBAL:
 			out("leaq %s(%%rip), %%rax\n", sym->label);
-			out("movq %%rbx, (%%rax)\n");
+			emitstorereg(8);
 			break;
 		case SCAUTO:
 			out("leaq %d(%%rbp), %%rax\n", sym->offset);
-			out("movq %%rbx, (%%rax)\n");
+			emitstorereg(8);
 			break;
 		}
 		break;


Don't use X86_64_ELF_NONPIC_HACK for +RTS -xp

Summary:
When `+RTS -xp` is passed, when don't need the X86_64_ELF_NONPIC_HACK,
becasue the relocation offset should only be out of range if

* the object file was not compiled with `-fPIC -fexternal-dynamic-refs`;
* ghc generates non-pic code while it should (e.g. #15723)

In either case, we should print an error message rather that silently
attempt to use a hacky workaround that may not work.

This could have made debugging #15723 and #15729 much easier.

Test Plan:
Run this in a case where ghci used to crash becasue of T15723. Now we
see helpful message like:

```
ghc-iserv-prof: R_X86_64_PC32 relocation out of range:
stmzm2zi4zi4zi1zmJQn4hNPyYjP5m9AcbI88Ve_ControlziConcurrentziSTMziTMVar_readTMVar_C61n_cc
= 9b95ffac
```

Reviewers: simonmar, bgamari, erikd

Reviewed By: simonmar, bgamari

Subscribers: rwbarton, carter

Differential Revision: https://phabricator.haskell.org/D5233

--- rts/linker/Elf.c
+++ rts/linker/Elf.c
@@ -53,11 +53,13 @@
  * SILENTLY generate crashing code for data references.  This hack is
  * enabled by X86_64_ELF_NONPIC_HACK.
  *
- * One workaround is to use shared Haskell libraries.  This is
- * coming.  Another workaround is to keep the static libraries but
- * compile them with -fPIC, because that will generate PIC references
- * to data which can be relocated.  The PIC code is still too green to
- * do this systematically, though.
+ * One workaround is to use shared Haskell libraries. This is the case
+ * when dynamically-linked GHCi is used.
+ *
+ * Another workaround is to keep the static libraries but compile them
+ * with -fPIC -fexternal-dynamic-refs, because that will generate PIC
+ * references to data which can be relocated. This is the case when
+ * +RTS -xp is passed.
  *
  * See bug #781
  * See thread http://www.haskell.org/pipermail/cvs-ghc/2007-September/038458.html
@@ -74,7 +76,7 @@
  * Sym*_NeedsProto: the symbol is undefined and we add a dummy
  *                  default proto extern void sym(void);
  */
-#define X86_64_ELF_NONPIC_HACK 1
+#define X86_64_ELF_NONPIC_HACK (!RtsFlags.MiscFlags.linkerAlwaysPic)

 #if defined(sparc_HOST_ARCH)
 #  define ELF_TARGET_SPARC  /* Used inside <elf.h> */


gc: avoid 0-length C array

gc: avoid 0-length C array

R=golang-dev, ality
CC=golang-dev, rsc
http://codereview.appspot.com/5467066

Committer: Russ Cox <5ad239cb8a44f659eaaee0aa1ea5b94947abe557@golang.org>

--- src/cmd/gc/lex.c
+++ src/cmd/gc/lex.c
@@ -38,6 +38,7 @@
 	int *val;
 } exper[] = {
 //	{"rune32", &rune32},
+	{nil, nil},
 };

 static void
@@ -45,7 +46,7 @@
 {
 	int i;

-	for(i=0; i<nelem(exper); i++) {
+	for(i=0; exper[i].name != nil; i++) {
 		if(strcmp(exper[i].name, s) == 0) {
 			*exper[i].val = 1;
 			return;
@@ -75,7 +76,7 @@
 	static char buf[512];

 	strcpy(buf, "X");
-	for(i=0; i<nelem(exper); i++)
+	for(i=0; exper[i].name != nil; i++)
 		if(*exper[i].val)
 			seprint(buf+strlen(buf), buf+sizeof buf, ",%s", exper[i].name);
 	if(strlen(buf) == 1)


Storage.c: Pass a size to sys_icache_invalidate

The previous code passed an end pointer, but the interface takes a size
instead.

Fixes #12838.

Reviewers: austin, erikd, simonmar, bgamari

Reviewed By: simonmar, bgamari

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D2711

GHC Trac Issues: #12838

--- rts/sm/Storage.c
+++ rts/sm/Storage.c
@@ -1314,7 +1314,7 @@
    ------------------------------------------------------------------------- */

 #if (defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)) && defined(ios_HOST_OS)
-void sys_icache_invalidate(void *start, size_t len);
+#include <libkern/OSCacheControl.h>
 #endif

 /* On ARM and other platforms, we need to flush the cache after
@@ -1327,7 +1327,7 @@
   (void)exec_addr;
 #elif (defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)) && defined(ios_HOST_OS)
   /* On iOS we need to use the special 'sys_icache_invalidate' call. */
-  sys_icache_invalidate(exec_addr, ((unsigned char*)exec_addr)+len);
+  sys_icache_invalidate(exec_addr, len);
 #elif defined(__GNUC__)
   /* For all other platforms, fall back to a libgcc builtin. */
   unsigned char* begin = (unsigned char*)exec_addr;


gc: print error detail about failure to open import

R=ken2
CC=golang-dev
http://codereview.appspot.com/1872041

--- src/cmd/gc/lex.c
+++ src/cmd/gc/lex.c
@@ -384,7 +384,7 @@

 	imp = Bopen(namebuf, OREAD);
 	if(imp == nil) {
-		yyerror("can't open import: %Z", f->u.sval);
+		yyerror("can't open import: %Z: %r", f->u.sval);
 		errorexit();
 	}
 	file = strdup(namebuf);


gc: fix non-canonical import error message

Fixes #1142.

R=ken2
CC=golang-dev
https://golang.org/cl/2218046

--- src/cmd/gc/lex.c
+++ src/cmd/gc/lex.c
@@ -378,7 +378,7 @@
 	q[name->len] = '\0';
 	cleanname(q);
 	if(strlen(q) != name->len || memcmp(q, name->s, name->len) != 0) {
-		yyerror("non-canonical import name %Z (%s)", name->s, q);
+		yyerror("non-canonical import path %Z (should be %s)", name, q);
 		return 0;
 	}


separate local path lookup from standard package directories

R=ken
OCL=30760
CL=30779

--- src/cmd/gc/lex.c
+++ src/cmd/gc/lex.c
@@ -213,6 +213,19 @@
 	(*pp)->dir = dir;
 }

+// is this path a local name?  begins with ./ or ../ or /
+int
+islocalname(Strlit *name)
+{
+	if(name->len >= 1 && name->s[0] == '/')
+		return 1;
+	if(name->len >= 2 && strncmp(name->s, "./", 2) == 0)
+		return 1;
+	if(name->len >= 3 && strncmp(name->s, "../", 3) == 0)
+		return 1;
+	return 0;
+}
+
 int
 findpkg(Strlit *name)
 {
@@ -225,9 +238,19 @@
 		goarch = getenv("GOARCH");
 	}

-	// try .a before .6.  important for building libraries:
-	// if there is an array.6 in the array.a library,
-	// want to find all of array.a, not just array.6.
+	if(islocalname(name)) {
+		// try .a before .6.  important for building libraries:
+		// if there is an array.6 in the array.a library,
+		// want to find all of array.a, not just array.6.
+		snprint(namebuf, sizeof(namebuf), "%Z.a", name);
+		if(access(namebuf, 0) >= 0)
+			return 1;
+		snprint(namebuf, sizeof(namebuf), "%Z.%c", name, thechar);
+		if(access(namebuf, 0) >= 0)
+			return 1;
+		return 0;
+	}
+
 	for(p = idirs; p != nil; p = p->link) {
 		snprint(namebuf, sizeof(namebuf), "%s/%Z.a", p->dir, name);
 		if(access(namebuf, 0) >= 0)
@@ -236,13 +259,6 @@
 		if(access(namebuf, 0) >= 0)
 			return 1;
 	}
-
-	snprint(namebuf, sizeof(namebuf), "%Z.a", name);
-	if(access(namebuf, 0) >= 0)
-		return 1;
-	snprint(namebuf, sizeof(namebuf), "%Z.%c", name, thechar);
-	if(access(namebuf, 0) >= 0)
-		return 1;
 	if(goroot != nil) {
 		snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s/%Z.a", goroot, goos, goarch, name);
 		if(access(namebuf, 0) >= 0)


Added ability to get the nth element from an abstract array type.

--- unsupported/Eigen/CXX11/src/Core/util/EmulateCXX11Meta.h
+++ unsupported/Eigen/CXX11/src/Core/util/EmulateCXX11Meta.h
@@ -181,6 +181,15 @@
   return array;
 }

+template<std::size_t I, class Head, class Tail>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(type_list<Head, Tail>& a) {
+  return get<I, type_list<Head, Tail> >::value;
+}
+template<std::size_t I, class Head, class Tail>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(const type_list<Head, Tail>& a) {
+  return get<I, type_list<Head, Tail> >::value;
+}
+
 template<std::size_t n, typename t>
 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, n>& a) {
   t prod = 1;
@@ -196,8 +205,8 @@
 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(array<T,N>& a) {
   return a[I];
 }
-template<std::size_t I, class T, std::size_t N> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
-const T& array_get(const array<T,N>& a) {
+template<std::size_t I, class T, std::size_t N>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const array<T,N>& a) {
   return a[I];
 }


Fixed a few more typos

Fixed a few more typos

--- unsupported/Eigen/CXX11/src/Tensor/TensorDimensionList.h
+++ unsupported/Eigen/CXX11/src/Tensor/TensorDimensionList.h
@@ -152,13 +152,13 @@

 template <typename Index, std::size_t Rank>
 struct all_indices_known_statically_impl<DimensionList<Index, Rank> > {
-  EIGEN_ALWAYS_INLINE bool operator() () const {
+  static EIGEN_ALWAYS_INLINE bool run() {
     return true;
   }
 };
 template <typename Index, std::size_t Rank>
 struct all_indices_known_statically_impl<const DimensionList<Index, Rank> > {
-  EIGEN_ALWAYS_INLINE bool operator() () const {
+  static EIGEN_ALWAYS_INLINE bool run() {
     return true;
   }
 };


egl: Correctly unbind contexts in eglReleaseThread.

MakeCurrent unbinds the current context of the current API.  Modify the
current API to make sure all contexts are correctly unbound.

--- src/egl/main/eglapi.c
+++ src/egl/main/eglapi.c
@@ -997,6 +997,7 @@
    /* unbind current contexts */
    if (!_eglIsCurrentThreadDummy()) {
       _EGLThreadInfo *t = _eglGetCurrentThread();
+      EGLint api_index = t->CurrentAPIIndex;
       EGLint i;

       for (i = 0; i < _EGL_API_NUM_APIS; i++) {
@@ -1004,9 +1005,12 @@
          if (ctx) {
             _EGLDisplay *disp = ctx->Resource.Display;
             _EGLDriver *drv = disp->Driver;
+            t->CurrentAPIIndex = i;
             (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
          }
       }
+
+      t->CurrentAPIIndex = api_index;
    }

    _eglDestroyCurrentThread();


eglapi: add entrypoint for eglDestroySyncKHR

Signed-off-by: Eric Engestrom <96f164ad4d9b2b0dacf8ebee2bb1eeb3aa69adf1@engestrom.ch>
Reviewed-by: Emil Velikov <f20878473f414da183da19ee25c8722cc1d711e4@collabora.com>

--- src/egl/main/eglapi.c
+++ src/egl/main/eglapi.c
@@ -1726,15 +1726,11 @@
 }

-EGLBoolean EGLAPIENTRY
-eglDestroySync(EGLDisplay dpy, EGLSync sync)
-{
-   _EGLDisplay *disp = _eglLockDisplay(dpy);
-   _EGLSync *s = _eglLookupSync(sync, disp);
-   _EGLDriver *drv;
-   EGLBoolean ret;
-
-   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+static EGLBoolean
+_eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
+{
+   _EGLDriver *drv;
+   EGLBoolean ret;

    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
    assert(disp->Extensions.KHR_reusable_sync ||
@@ -1745,6 +1741,24 @@
    ret = drv->API.DestroySyncKHR(drv, disp, s);

    RETURN_EGL_EVAL(disp, ret);
+}
+
+EGLBoolean EGLAPIENTRY
+eglDestroySync(EGLDisplay dpy, EGLSync sync)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+   return _eglDestroySync(disp, s);
+}
+
+static EGLBoolean EGLAPIENTRY
+eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+   return _eglDestroySync(disp, s);
 }

@@ -2378,7 +2392,7 @@
       { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
       { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
       { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR },
-      { "eglDestroySyncKHR", (_EGLProc) eglDestroySync },
+      { "eglDestroySyncKHR", (_EGLProc) eglDestroySyncKHR },
       { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSync },
       { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
       { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },


fix to XTogglebtn not showing frame issue 275

--- src/elem/XTogglebtn.c
+++ src/elem/XTogglebtn.c
@@ -254,6 +254,9 @@
 {
   // Work out the sizes of the inner rectangles
   gslc_tsRect rInner = gslc_ExpandRect(pElem->rElem,-1,-1);
+
+  // frame enabled?
+  bool bFrameEn  = pElem->nFeatures & GSLC_ELEM_FEA_FRAME_EN;

   // work out our circle positions
   uint16_t nRadius  = rInner.h / 2;
@@ -267,11 +270,23 @@
     gslc_DrawFillRoundRect(pGui,rInner,nRadius,pTogglebtn->colOnState);
     // place thumb on right-hand side
     gslc_DrawFillCircle(pGui,nRightX-1,nRightY,nRadius-1,pTogglebtn->colThumb);
+    if (bFrameEn) {
+// ON HX8357 and ILI9341 with TFT_eSPI if we do rounded rect frame we get
+// something that looks like two reversed parenthesis )button( around button
+      gslc_DrawFrameCircle(pGui,nRightX,nRightY,nRadius-1,pElem->colElemFrame);
+//      gslc_DrawFrameRoundRect(pGui,pElem->rElem,pElem->rElem.h,pElem->colElemFrame);
+      gslc_DrawFrameRoundRect(pGui,rInner,nRadius,pElem->colElemFrame);
+    }
   } else {
     // draw our main body
     gslc_DrawFillRoundRect(pGui,rInner,nRadius,pTogglebtn->colOffState);
     // place thumb on left-hand side
     gslc_DrawFillCircle(pGui,nLeftX,nLeftY,nRadius-1,pTogglebtn->colThumb);
+    if (bFrameEn) {
+      gslc_DrawFrameCircle(pGui,nLeftX,nLeftY,nRadius-1,pElem->colElemFrame);
+//      gslc_DrawFrameRoundRect(pGui,,pElem->rElem.h,pElem->colElemFrame);
+      gslc_DrawFrameRoundRect(pGui,rInner,nRadius,pElem->colElemFrame);
+    }
   }
 }


Forward double-click events

Forward double-click events

Double-clicks were not sent to the device anymore since the
"double-click on black borders" feature.

When a double click occurs inside the device screen, send the event to
the device normally.

Fixes <https://github.com/Genymobile/scrcpy/issues/97>.

--- app/src/inputmanager.c
+++ app/src/inputmanager.c
@@ -240,10 +240,11 @@
             SDL_bool outside_device_screen =
                     event->x < 0 || event->x >= input_manager->screen->frame_size.width ||
                     event->y < 0 || event->y >= input_manager->screen->frame_size.height;
-                if (outside_device_screen) {
-                    screen_resize_to_fit(input_manager->screen);
-                }
-            return;
+            if (outside_device_screen) {
+                screen_resize_to_fit(input_manager->screen);
+                return;
+            }
+            // otherwise, send the click event to the device
         }
     };
     struct control_event control_event;


rohc_stats: avoid setting trace callback in silent mode

--- app/stats/rohc_stats.c
+++ app/stats/rohc_stats.c
@@ -1,6 +1,6 @@
 /*
  * Copyright 2010,2012,2013,2014 Didier Barvaux
- * Copyright 2012 Viveris Technologies
+ * Copyright 2012,2017 Viveris Technologies
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -355,12 +355,15 @@
 		goto close_input;
 	}

-	/* set the callback for traces on compressor */
-	if(!rohc_comp_set_traces_cb2(comp, print_rohc_traces, NULL))
-	{
-		fprintf(stderr, "failed to set the callback for traces on "
-		        "compressor\n");
-		goto destroy_comp;
+	/* set the callback for traces on compressor only in verbose mode */
+	if(is_verbose)
+	{
+		if(!rohc_comp_set_traces_cb2(comp, print_rohc_traces, NULL))
+		{
+			fprintf(stderr, "failed to set the callback for traces on "
+			        "compressor\n");
+			goto destroy_comp;
+		}
 	}

 	/* enable periodic refreshes based on inter-packet delay */
@@ -556,13 +559,10 @@
                               const char *const format,
                               ...)
 {
-	if(is_verbose)
-	{
-		va_list args;
-		va_start(args, format);
-		vfprintf(stderr, format, args);
-		va_end(args);
-	}
+	va_list args;
+	va_start(args, format);
+	vfprintf(stderr, format, args);
+	va_end(args);
 }


Warning fix.

Warning fix.

--- api/src/c/api-client.c
+++ api/src/c/api-client.c
@@ -94,8 +94,7 @@
 {
   *res = malloc(size * 3 + 1);
   char * out = *res;
-  int i;
-  for (i = 0; i < size; ++i)
+  for (size_t i = 0; i < size; ++i)
   {
     unsigned char c = (unsigned char)(s[i]);
     switch (c)


correct hardware revision mask.

correct hardware revision mask.

--- dev/ic/rtl81x9reg.h
+++ dev/ic/rtl81x9reg.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: rtl81x9reg.h,v 1.33 2006/11/24 04:27:17 brad Exp $	*/
+/*	$OpenBSD: rtl81x9reg.h,v 1.34 2006/11/26 10:58:16 jsg Exp $	*/

 /*
  * Copyright (c) 1997, 1998
@@ -140,7 +140,7 @@
 #define RL_TXCFG_LOOPBKTST	0x00060000	/* loopback test */
 #define RL_TXCFG_IFG2		0x00080000	/* 8169 only */
 #define RL_TXCFG_IFG		0x03000000	/* interframe gap */
-#define RL_TXCFG_HWREV		0x7CC00000
+#define RL_TXCFG_HWREV		0x7C800000

 #define RL_LOOPTEST_OFF		0x00000000
 #define RL_LOOPTEST_ON		0x00020000


Replace the last occurence of (long long) and %qd with
(intmax_t) and %jd, which is the right way to printf
an off_t in the presence of <stdint.h>.

Submitted by:	Nick Leuta

--- libexec/ftpd/ftpd.c
+++ libexec/ftpd/ftpd.c
@@ -3175,9 +3175,9 @@

 	if (statfd >= 0 && getwd(path) != NULL) {
 		time(&now);
-		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n",
+		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%jd!%ld\n",
 			ctime(&now)+4, ident, remotehost,
-			path, name, (long long)size,
+			path, name, (intmax_t)size,
 			(long)(now - start + (now == start)));
 		write(statfd, buf, strlen(buf));
 	}


actual function for adding a background, high priority task

--- libgearman/client.c
+++ libgearman/client.c
@@ -356,6 +356,20 @@
                                                     gearman_return_t *ret_ptr)
 {
   return _client_add_task(client, task, fn_arg, GEARMAN_COMMAND_SUBMIT_JOB_BG,
+                          function_name, unique, workload, workload_size,
+                          ret_ptr);
+}
+
+gearman_task_st *gearman_client_add_task_high_background(gearman_client_st *client,
+                                                         gearman_task_st *task,
+                                                         const void *fn_arg,
+                                                         const char *function_name,
+                                                         const char *unique,
+                                                         const void *workload,
+                                                         size_t workload_size,
+                                                         gearman_return_t *ret_ptr)
+{
+  return _client_add_task(client, task, fn_arg, GEARMAN_COMMAND_SUBMIT_JOB_HIGH_BG,
                           function_name, unique, workload, workload_size,
                           ret_ptr);
 }


break

break

--- libjl777/SuperNET.c
+++ libjl777/SuperNET.c
@@ -214,7 +214,10 @@
                             {
                                 copy_cJSON(errstr,cJSON_GetObjectItem(argjson,"error"));
                                 if ( strlen(errstr) > 0 || strcmp(buf2,waitfor) == 0 )
+                                {
                                     retstrs[gatewayid] = retstr, retstr = 0;
+                                    if ( retstrs[0] != 0 && retstrs[1] != 0 && retstrs[2] != 0 )
+                                        break;
                             }
                         }
                     }


rebroadcast

rebroadcast

--- libjl777/ramchain.h
+++ libjl777/ramchain.h
@@ -3248,7 +3248,7 @@

 uint64_t _find_pending_transfers(uint64_t *pendingredeemsp,struct ramchain_info *ram)
 {
-    int32_t j,disable_newsends,specialsender,specialreceiver;
+    int32_t i,j,disable_newsends,specialsender,specialreceiver;
     char sender[64],receiver[64],withdrawaddr[512],*destaddr;
     struct NXT_assettxid *tp;
     struct NXT_asset *ap;
@@ -3256,7 +3256,7 @@
     uint64_t orphans = 0;
     *pendingredeemsp = 0;
     disable_newsends = (ram->numpendingsends > 0);
-    if ( disable_newsends != 0 )
+    if ( disable_newsends != 0 && ram->S.gatewayid >= 0 )
     {
         if ( ram->pendingticks++ > MAX_PENDINGSENDS_TICKS )
         {
@@ -3264,6 +3264,14 @@
             ram_add_pendingsend(0,ram,0,0);
             ram->pendingticks = disable_newsends = 0;
             printf("resume find_pending_transfers\n");
+        }
+        else if ( (ram->pendingticks % 10) == 9 )
+        {
+            for (i=0; i<ram->numpendingsends; i++)
+                if ( (tp= ram->pendingsends[i]) != 0 )
+                    for (j=0; j<ram->numgateways; j++)
+                        if ( ram->S.gatewayid != j && (cointx= tp->pendingsends[j]) != 0 )
+                            ram_send_cointx(ram,cointx);
         }
     }
     else ram->pendingticks = 0;


Changed connect with timeout to use poll() instead if socket() to avoid problems with many open files

--- libmysql/libmysql.c
+++ libmysql/libmysql.c
@@ -40,14 +40,17 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #ifdef HAVE_SELECT_H
-#  include <select.h>
+#include <select.h>
 #endif
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
-#endif
+#ifdef HAVE_POLL
+#include <sys/poll.h>
+#endif
+#endif /* !defined(MSDOS) && !defined(__WIN__) */
 #ifdef HAVE_SYS_UN_H
-#  include <sys/un.h>
+#include <sys/un.h>
 #endif
 #if defined(THREAD) && !defined(__WIN__)
 #include <my_pthread.h>				/* because of signal()	*/
@@ -148,9 +151,12 @@
 			 const char* user,
 			 const char* passwd);

+#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__))
+static int wait_for_data(my_socket fd, uint timeout);
+#endif

 /****************************************************************************
-  A modified version of connect().  connect2() allows you to specify
+  A modified version of connect().  my_connect() allows you to specify
   a timeout value, in seconds, that we should wait until we
   derermine we can't connect to a particular host.  If timeout is 0,
   my_connect() will behave exactly like connect().
@@ -158,48 +164,82 @@
   Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
 *****************************************************************************/

-int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
+int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
 	       uint timeout)
 {
 #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
-  return connect(s, (struct sockaddr*) name, namelen);
+  return connect(fd, (struct sockaddr*) name, namelen);
 #else
   int flags, res, s_err;
+
+  /*
+    If they passed us a timeout of zero, we should behave
+    exactly like the normal connect() call does.
+  */
+
+  if (timeout == 0)
+    return connect(fd, (struct sockaddr*) name, namelen);
+
+  flags = fcntl(fd, F_GETFL, 0);	  /* Set socket to not block */
+#ifdef O_NONBLOCK
+  fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
+#endif
+
+  res= connect(fd, (struct sockaddr*) name, namelen);
+  s_err= errno;			/* Save the error... */
+  fcntl(fd, F_SETFL, flags);
+  if ((res != 0) && (s_err != EINPROGRESS))
+  {
+    errno= s_err;			/* Restore it */
+    return(-1);
+  }
+  if (res == 0)				/* Connected quickly! */
+    return(0);
+  return wait_for_data(fd, timeout);
+#endif
+}
+
+
+/*
+  Wait up to timeout seconds for a connection to be established.
+
+  We prefer to do this with poll() as there is no limitations with this.
+  If not, we will use select()
+*/
+
+#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__))
+
+static int wait_for_data(my_socket fd, uint timeout)
+{
+#ifdef HAVE_POLL
+  struct pollfd ufds;
+  int res;
+
+  ufds.fd= fd;
+  ufds.events= POLLIN | POLLPRI;
+  if (!(res= poll(&ufds, 1, (int) timeout*1000)))
+  {
+    errno= EINTR;
+    return -1;
+  }
+  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
+    return -1;
+  return 0;
+#else
   SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
   fd_set sfds;
   struct timeval tv;
   time_t start_time, now_time;
+  int res, s_err;
+
+  if (fd >= FD_SETSIZE)				/* Check if wrong error */
+    return 0;					/* Can't use timeout */

   /*
-    If they passed us a timeout of zero, we should behave
-    exactly like the normal connect() call does.
-  */
-
-  if (timeout == 0)
-    return connect(s, (struct sockaddr*) name, namelen);
-
-  flags = fcntl(s, F_GETFL, 0);		  /* Set socket to not block */
-#ifdef O_NONBLOCK
-  fcntl(s, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
-#endif
-
-  res = connect(s, (struct sockaddr*) name, namelen);
-  s_err = errno;			/* Save the error... */
-  fcntl(s, F_SETFL, flags);
-  if ((res != 0) && (s_err != EINPROGRESS))
-  {
-    errno = s_err;			/* Restore it */
-    return(-1);
-  }
-  if (res == 0)				/* Connected quickly! */
-    return(0);
-
-  /*
-    Otherwise, our connection is "in progress."  We can use
-    the select() call to wait up to a specified period of time
-    for the connection to suceed.  If select() returns 0
-    (after waiting howevermany seconds), our socket never became
-    writable (host is probably unreachable.)  Otherwise, if
+    Our connection is "in progress."  We can use the select() call to wait
+    up to a specified period of time for the connection to suceed.
+    If select() returns 0 (after waiting howevermany seconds), our socket
+    never became writable (host is probably unreachable.)  Otherwise, if
     select() returns 1, then one of two conditions exist:

     1. An error occured.  We use getsockopt() to check for this.
@@ -212,7 +252,7 @@
   */

   FD_ZERO(&sfds);
-  FD_SET(s, &sfds);
+  FD_SET(fd, &sfds);
   /*
     select could be interrupted by a signal, and if it is,
     the timeout should be adjusted and the select restarted
@@ -226,10 +266,10 @@
     tv.tv_sec = (long) timeout;
     tv.tv_usec = 0;
 #if defined(HPUX10) && defined(THREAD)
-    if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
+    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
       break;
 #else
-    if ((res = select(s+1, NULL, &sfds, NULL, &tv)) > 0)
+    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
       break;
 #endif
     if (res == 0)					/* timeout */
@@ -247,7 +287,7 @@
   */

   s_err=0;
-  if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
+  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
     return(-1);

   if (s_err)
@@ -256,9 +296,9 @@
     return(-1);					/* but return an error... */
   }
   return (0);					/* ok */
-
-#endif
-}
+#endif /* HAVE_POLL */
+}
+#endif /* defined(__WIN__) || defined(OS2) || defined(__NETWARE__) */

 /*
   Create a named pipe connection


Add support for PHP 7.3

Add support for PHP 7.3

--- scalar_objects.c
+++ scalar_objects.c
@@ -28,7 +28,11 @@

 #ifdef ZEND_ENGINE_3
 typedef size_t strlen_t;
-# define EX_LITERAL(op) EX_CONSTANT(op)
+# if PHP_VERSION_ID >= 70300
+#  define EX_LITERAL(opline, op) RT_CONSTANT(opline, op)
+# else
+#  define EX_LITERAL(opline, op) EX_CONSTANT(op)
+# endif
 # define SO_THIS (Z_OBJ(EX(This)) ? &EX(This) : NULL)
 # define FREE_OP(should_free) \
 	if (should_free) { \
@@ -41,7 +45,7 @@
 # define Z_TRY_ADDREF_P(zv) Z_ADDREF_P(zv)
 # define ZVAL_DEREF(zv)

-# define EX_LITERAL(op) (op).literal
+# define EX_LITERAL(opline, op) (op).literal
 # define SO_THIS EG(This)
 # define FREE_OP(should_free)                                           \
     if (should_free.var) {                                             \
@@ -68,12 +72,13 @@

 static zval *get_zval_ptr_safe(
-	int op_type, const znode_op *node, const zend_execute_data *execute_data
+	const zend_op *opline, int op_type, const znode_op *node,
+	const zend_execute_data *execute_data
 ) {
 #ifdef ZEND_ENGINE_3
 	switch (op_type) {
 		case IS_CONST:
-			return EX_CONSTANT(*node);
+			return EX_LITERAL(opline, *node);
 		case IS_CV:
 		case IS_TMP_VAR:
 		case IS_VAR:
@@ -104,20 +109,23 @@
 }

 static zval *get_object_zval_ptr_safe(
-	int op_type, const znode_op *node, zend_execute_data *execute_data TSRMLS_DC
+	const zend_op *opline, int op_type, const znode_op *node,
+	zend_execute_data *execute_data TSRMLS_DC
 ) {
 	if (op_type == IS_UNUSED) {
 		return SO_THIS;
 	} else {
-		return get_zval_ptr_safe(op_type, node, execute_data);
+		return get_zval_ptr_safe(opline, op_type, node, execute_data);
 	}
 }

 static zval *get_zval_ptr_real(
-	int op_type, const znode_op *node, const zend_execute_data *execute_data,
-	zend_free_op *should_free, int type TSRMLS_DC
+	const zend_op *opline, int op_type, const znode_op *node,
+	const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC
 ) {
-#ifdef ZEND_ENGINE_2_5
+#if PHP_VERSION_ID >= 70300
+	zval *zv = zend_get_zval_ptr(opline, op_type, node, execute_data, should_free, type TSRMLS_CC);
+#elif defined(ZEND_ENGINE_2_5)
 	zval *zv = zend_get_zval_ptr(op_type, node, execute_data, should_free, type TSRMLS_CC);
 #else
 	zval *zv = zend_get_zval_ptr(op_type, node, execute_data->Ts, should_free, type TSRMLS_CC);
@@ -127,7 +135,7 @@
 }

 static zval *get_object_zval_ptr_real(
-	int op_type, const znode_op *node, zend_execute_data *execute_data,
+	const zend_op *opline, int op_type, const znode_op *node, zend_execute_data *execute_data,
 	zend_free_op *should_free, int type TSRMLS_DC
 ) {
 	if (op_type == IS_UNUSED) {
@@ -142,7 +150,7 @@
 #endif
 		return SO_THIS;
 	} else {
-		return get_zval_ptr_real(op_type, node, execute_data, should_free, type TSRMLS_CC);
+		return get_zval_ptr_real(opline, op_type, node, execute_data, should_free, type TSRMLS_CC);
 	}
 }

@@ -282,8 +290,8 @@
 	/* First we fetch the ops without refcount changes or errors. Then we check whether we want
 	 * to handle this opcode ourselves or fall back to the original opcode. Only once we know for
 	 * certain that we will not fall back the ops are fetched for real. */
-	obj = get_object_zval_ptr_safe(opline->op1_type, &opline->op1, execute_data TSRMLS_CC);
-	method = get_zval_ptr_safe(opline->op2_type, &opline->op2, execute_data);
+	obj = get_object_zval_ptr_safe(opline, opline->op1_type, &opline->op1, execute_data TSRMLS_CC);
+	method = get_zval_ptr_safe(opline, opline->op2_type, &opline->op2, execute_data);

 	if (!obj || Z_TYPE_P(obj) == IS_OBJECT || Z_TYPE_P(method) != IS_STRING) {
 		return ZEND_USER_OPCODE_DISPATCH;
@@ -299,15 +307,15 @@
 	} else {
 		fbc = zend_std_get_static_method(
 			ce, Z_STR_P(method),
-			opline->op2_type == IS_CONST ? EX_LITERAL(opline->op2) + 1 : NULL TSRMLS_CC
+			opline->op2_type == IS_CONST ? EX_LITERAL(opline, opline->op2) + 1 : NULL TSRMLS_CC
 		);
 	}

 	method = get_zval_ptr_real(
-		opline->op2_type, &opline->op2, execute_data, &free_op2, BP_VAR_R TSRMLS_CC
+		opline, opline->op2_type, &opline->op2, execute_data, &free_op2, BP_VAR_R TSRMLS_CC
 	);
 	obj = get_object_zval_ptr_real(
-		opline->op1_type, &opline->op1, execute_data, &free_op1, BP_VAR_R TSRMLS_CC
+		opline, opline->op1_type, &opline->op1, execute_data, &free_op1, BP_VAR_R TSRMLS_CC
 	);

 	if (!fbc) {


Skip asn1 zeroize if freeing shallow pointers

This skips zeroizing additional pointers to data.
(Note: actual sensitive data should still be zeroized when freed.)

Signed-off-by: Glenn Strauss <e14964668061ab2d098d4c9d057052a0e88042c5@gluelogic.com>

--- library/asn1parse.c
+++ library/asn1parse.c
@@ -314,7 +314,6 @@
     while( seq != NULL )
     {
         mbedtls_asn1_sequence *next = seq->next;
-        mbedtls_platform_zeroize( seq, sizeof( *seq ) );
         mbedtls_free( seq );
         seq = next;
     }
@@ -450,7 +449,8 @@
     while( ( cur = *head ) != NULL )
     {
         *head = cur->next;
-        mbedtls_asn1_free_named_data( cur );
+        mbedtls_free( cur->oid.p );
+        mbedtls_free( cur->val.p );
         mbedtls_free( cur );
     }
 }
@@ -460,7 +460,6 @@
     for( mbedtls_asn1_named_data *next; name != NULL; name = next )
     {
         next = name->next;
-        mbedtls_platform_zeroize( name, sizeof( *name ) );
         mbedtls_free( name );
     }
 }


extmod/modwebsocket: Make compatible with non-default object models.

--- extmod/modwebsocket.c
+++ extmod/modwebsocket.c
@@ -73,11 +73,11 @@
     if (n_args > 1 && args[1] == mp_const_true) {
         o->opts |= BLOCKING_WRITE;
     }
-    return o;
+    return  MP_OBJ_FROM_PTR(o);
 }

 STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
-    mp_obj_websocket_t *self = self_in;
+    mp_obj_websocket_t *self =  MP_OBJ_TO_PTR(self_in);
     const mp_stream_p_t *stream_p = mp_get_stream_raise(self->sock, MP_STREAM_OP_READ);
     while (1) {
         if (self->to_recv != 0) {
@@ -219,7 +219,7 @@
 }

 STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
-    mp_obj_websocket_t *self = self_in;
+    mp_obj_websocket_t *self =  MP_OBJ_TO_PTR(self_in);
     assert(size < 0x10000);
     byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)};
     int hdr_sz;


Fix typo.

Fix typo.

Co-Authored-By: chrisdembia <6d9b70b6769e7cc306c06b742df06abc65802691@cornell.edu>

--- OpenSim/Common/Component.h
+++ OpenSim/Common/Component.h
@@ -3053,7 +3053,7 @@
             rootOfConnectee.getName() + "' to '" + myRoot.getName() + "'?");

         std::string connecteePath = connectee->getRelativePathName(getOwner());
-        // If the relative path start with ".." the use an absolute path
+        // If the relative path starts with ".." then use an absolute path
         // instead.
         if (connecteePath.size() >= 2 && connecteePath.substr(0, 2) == "..")
             connecteePath = connectee->getAbsolutePathString();


app/testpmd: change rxfreet default to 32

To improve performance by using bulk alloc or vectored RX routines, we
need to set rx free threshold (rxfreet) value to 32, so make this the
testpmd default.

Thirty-two is the minimum setting needed to enable either the
bulk alloc or vector RX routines inside the ixgbe driver, so it's
best made the default for that reason. Please see
"check_rx_burst_bulk_alloc_preconditions()" in ixgbe_rxtx.c, and
RX function assignment logic in "ixgbe_dev_rx_queue_setup()" in
the same file.

The difference in IO performance for testpmd when called without any
optional parameters, and using 10G NICs using the ixgbe driver, can be
significant - approx 25% or more.

Signed-off-by: Bruce Richardson <66b9e8e8fbd5e9f41f91b0af050876182ce9d0e4@intel.com>
Acked-by: Pablo de Lara <28355d9cfe41bb8148aea0fb24f47aae8f4217a1@intel.com>

--- app/test-pmd/testpmd.c
+++ app/test-pmd/testpmd.c
@@ -225,7 +225,9 @@
 /*
  * Configurable value of RX free threshold.
  */
-uint16_t rx_free_thresh = 0; /* Immediately free RX descriptors by default. */
+uint16_t rx_free_thresh = 32; /* Refill RX descriptors once every 32 packets,
+		This setting is needed for ixgbe to enable bulk alloc or vector
+		receive functionality. */

 /*
  * Configurable value of RX drop enable.


minor formatting

minor formatting

--- OpenSim/Common/Component.h
+++ OpenSim/Common/Component.h
@@ -1060,7 +1060,9 @@
      *  3. It takes only one input, which is const SimTK::State&
      *
      * If these are not true for your case, then use the more general method
-     * Component::constructOutput(const std::string&, const std::function<T(const SimTK::State&)>, const SimTK::Stage&).
+     * Component::constructOutput(const std::string&,
+     *                            const std::function<T(const SimTK::State&)>,
+     *                            const SimTK::Stage&).
      *
      * Here's an example. Say your Component has a method calcForce:
      *  @code
@@ -1087,20 +1089,23 @@
 	* Construct an Output (wire) for the Component as function of the State.
 	* Specifiy a (member) function of the state implemented by this component to
 	* be an Output and include the Stage that output is dependent on. If no
-    * Stage is specified it defaults to Acceleration. Here's an example. Say you have a class Markers that manages markers, you have an instance of this class as a member variable in your Component, and Markers has a method `Vec3 Markers\:\:calcMarkerPos(const SimTK\:\:State& s, std\:\:string marker);` to compute
-    * motion capture marker positions, given the name of a marker.
-     *  @code
-     *  constructOutput<SimTK::Vec3>("ankle_marker_pos",
-     *          std::bind(&Markers::calcMarkerPos, _markers,
-     *          std::placeholders::_1, "ankle"),
-     *          SimTK::Stage::Position);
-	 *  @endcode
+    * Stage is specified it defaults to Acceleration. Here's an example. Say you
+    * have a class Markers that manages markers, you have an instance of this class
+    * as a member variable in your Component, and Markers has a method
+    * `Vec3 Markers\:\:calcMarkerPos(const SimTK\:\:State& s, std\:\:string marker);`
+    * to compute motion capture marker positions, given the name of a marker.
+    *  @code
+    *  constructOutput<SimTK::Vec3>("ankle_marker_pos",
+    *          std::bind(&Markers::calcMarkerPos, _markers,
+    *          std::placeholders::_1, "ankle"),
+    *          SimTK::Stage::Position);
+    *  @endcode
 	*/
 	template <typename T>
 	void constructOutput(const std::string& name,
 		const std::function<T(const SimTK::State&)> outputFunction,
 		const SimTK::Stage& dependsOn = SimTK::Stage::Acceleration) {
-		_outputsTable[name] = new Output<T>(name, outputFunction, dependsOn);
+		    _outputsTable[name] = new Output<T>(name, outputFunction, dependsOn);
 	}

 	/**


Handle SIGUSR1 for forced refreshes

Handle SIGUSR1 for forced refreshes

At some point one might want to force a refresh for example after
checking email or changing the volume. Sending a SIGUSR1 achieves this
now

--- slstatus.c
+++ slstatus.c
@@ -18,7 +18,7 @@
 };

 char buf[1024];
-static int done;
+static volatile sig_atomic_t done;
 static Display *dpy;

 #include "config.h"
@@ -26,9 +26,8 @@
 static void
 terminate(const int signo)
 {
-	(void)signo;
-
-	done = 1;
+	if (signo != SIGUSR1)
+		done = 1;
 }

 static void
@@ -72,6 +71,8 @@
 	act.sa_handler = terminate;
 	sigaction(SIGINT,  &act, NULL);
 	sigaction(SIGTERM, &act, NULL);
+	act.sa_flags |= SA_RESTART;
+	sigaction(SIGUSR1, &act, NULL);

 	if (!sflag && !(dpy = XOpenDisplay(NULL))) {
 		die("XOpenDisplay: Failed to open display");


Add methods to DataTable to get/set table metadata directly without needing to operate on another object.

--- OpenSim/Common/DataTable.h
+++ OpenSim/Common/DataTable.h
@@ -115,6 +115,19 @@
     using Exception::Exception;
 };

+class KeyExists : public Exception {
+public:
+    KeyExists(const std::string& file,
+              size_t line,
+              const std::string& func,
+              const std::string& key) :
+        Exception(file, line, func) {
+        std::string msg = "Key '" + key + "' not found.";
+
+        addMessage(msg);
+    }
+};
+
 /** AbstractDataTable is the base-class of all DataTable_(templated) allowing
 storage of DataTable_ templated on different types to be stored in a container
 like std::vector. DataTable_ represents a matrix and an additional column. The
@@ -154,6 +167,31 @@

     /// @name MetaData accessors/mutators.
     /// @{
+
+    /** Add key-value pair to the table metadata.
+
+    \tparam Value Type of the value. This need not be specified explicitly in
+                  most cases. It will be deduced automatically.
+
+    \throws KeyExists If the key provided already exists in table metadata.   */
+    template<typename Value>
+    void addTableMetaData(const std::string& key, const Value& value) {
+        OPENSIM_THROW_IF(!_tableMetaData.setValueForKey(key, value),
+                         KeyExists,
+                         key);
+    }
+
+    /** Get table metadata for a given key.
+
+    \tparam Value Type of the value to be retrieved. For example if the metadata
+                  contains key-value pair ("sample-rate", 200), this could be
+                  specified as 'unsigned'.
+
+    \throws KeyNotFound If the key provided is not found in table metadata.   */
+    template<typename Value>
+    Value getTableMetaData(const std::string& key) {
+        return _tableMetaData.getValueForKey(key).getValue<Value>();
+    }

     /** Get metadata associated with the table.                               */
     const TableMetaData& getTableMetaData() const {


wifi_essid: add boundary check && prevent the use of direct string literal as a format string in snprintf()

--- slstatus.c
+++ slstatus.c
@@ -717,7 +717,8 @@

 	memset(&wreq, 0, sizeof(struct iwreq));
 	wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
-	sprintf(wreq.ifr_name, iface);
+	snprintf(wreq.ifr_name, ifrn_name, "%s", iface);
+
 	if (sockfd == -1) {
 		warn("Failed to get ESSID for interface %s", iface);
 		return smprintf("%s", UNKNOWN_STR);


RSL: clarify msgb free scheme in rsl

RSL: clarify msgb free scheme in rsl

--- src/common/rsl.c
+++ src/common/rsl.c
@@ -858,6 +858,8 @@
 	DEBUGP(DRLL, "%s Rx RLL %s Abis -> LAPDm\n", gsm_lchan_name(lchan),
 		rsl_msg_name(rh->c.msg_type));

+	/* exception: RLL messages are _NOT_ freed as they are now
+	 * owned by LAPDm which might have queued them */
 	return lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch);
 }

@@ -1036,13 +1038,17 @@

 	switch (dch->c.msg_type) {
 	case RSL_MT_CHAN_ACTIV:
-		return rsl_rx_chan_activ(msg);
+		ret = rsl_rx_chan_activ(msg);
+		break;
 	case RSL_MT_RF_CHAN_REL:
-		return rsl_rx_rf_chan_rel(msg);
+		ret = rsl_rx_rf_chan_rel(msg);
+		break;
 	case RSL_MT_SACCH_INFO_MODIFY:
-		return rsl_rx_sacch_inf_mod(msg);
+		ret = rsl_rx_sacch_inf_mod(msg);
+		break;
 	case RSL_MT_DEACTIVATE_SACCH:
-		return bts_model_rsl_deact_sacch(msg->lchan);
+		ret = bts_model_rsl_deact_sacch(msg->lchan);
+		break;
 	case RSL_MT_ENCR_CMD:
 	case RSL_MT_MODE_MODIFY_REQ:
 	case RSL_MT_PHY_CONTEXT_REQ:
@@ -1139,6 +1145,8 @@
 	switch (rslh->msg_discr & 0xfe) {
 	case ABIS_RSL_MDISC_RLL:
 		ret = rsl_rx_rll(trx, msg);
+		/* exception: RLL messages are _NOT_ freed as they are now
+		 * owned by LAPDm which might have queued them */
 		break;
 	case ABIS_RSL_MDISC_COM_CHAN:
 		ret = rsl_rx_cchan(trx, msg);
@@ -1159,5 +1167,8 @@
 		ret = -EINVAL;
 	}

+	/* we don't free here, as rsl_rx{cchan,dchan,trx,ipaccess,rll} are
+	 * responsible for owning the msg */
+
 	return ret;
 }


rsl: properly initialize MS/BS Power Control state

struct lchan_power_ctrl_state actually contains more fields,
which also must be initialized on CHANnel ACTIVation.

Change-Id: Id9719088fc6e9479c13e9b327a3466d9e2810a3a
Related: SYS#4918

--- src/common/rsl.c
+++ src/common/rsl.c
@@ -1154,14 +1154,18 @@
 		  gsm_lchans_name(lchan->state));

 	/* Initialize MS Power Control defaults */
-	lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0);
-	lchan->ms_power_ctrl.current = lchan->ms_power_ctrl.max;
-	lchan->ms_power_ctrl.fixed = true;
+	lchan->ms_power_ctrl = (struct lchan_power_ctrl_state) {
+		.max = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0),
+		.current = lchan->ms_power_ctrl.max,
+		.fixed = true,
+	};

 	/* Initialize BS Power Control defaults */
-	lchan->bs_power_ctrl.max = 2 * 15;
-	lchan->bs_power_ctrl.current = 0;
-	lchan->bs_power_ctrl.fixed = true;
+	lchan->bs_power_ctrl = (struct lchan_power_ctrl_state) {
+		.max = 2 * 15, /* maximum defined in 9.3.4 */
+		.current = 0,
+		.fixed = true,
+	};

 	rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));


Fix handling when username/password are NULL.

git-svn-id: 33305d871a58cfd02b407b81d5206d2a785211eb@824 159cb52c-178a-4f3c-8eb8-d0aff033d058

--- c/src/ta_data/ta_source/ta_sql/ta_sql.c
+++ c/src/ta_data/ta_source/ta_sql/ta_sql.c
@@ -48,6 +48,7 @@
  *  012504 MF,JS  Fix some memory leaks and perform integer/double cast
  *                for columns that represents a number (Bug #881950)
  *  013104 MF     Revert the TA_TRACE_RETURN/RETURN_ON_ERROR change.
+ *  112704 MF     Add handling of NULL for username and password.
  */

 /* Description:
@@ -254,8 +255,8 @@
       retCode = (*privData->minidriver->openConnection)(
          dbase,
          host,
-         TA_StringToChar(param->username),
-         TA_StringToChar(param->password),
+         param->username?TA_StringToChar(param->username):NULL,
+         param->password?TA_StringToChar(param->password):NULL,
          port,
          &privData->connection);
    }


Properites improved

Properites improved

--- filemgr/src/dirview.c
+++ filemgr/src/dirview.c
@@ -1076,5 +1076,10 @@
 	if (ent != NULL)
 	{
 		propShow(ent->path, ent->mime);
-	};
-};
+	}
+	else
+	{
+		FSMimeType *mime = fsGetType(data->location);
+		propShow(data->location, mime);
+	};
+};


Updated learning metric

Updated learning metric

--- learning/LSSLRTAStar.h
+++ learning/LSSLRTAStar.h
@@ -89,6 +89,18 @@
 	double HCost(const state &from, const state &to)
 	{ return HCost(m_pEnv, from, to); }

+	double GetMaxStateLearning()
+	{
+		double learned = 0;
+		for (typename LearnedHeuristic::const_iterator it = heur.begin(); it != heur.end(); it++)
+		{
+			double thisState = (*it).second.theHeuristic;
+			if (learned < thisState)
+				learned = thisState;
+		}
+		return learned;
+	}
+
 	virtual uint64_t GetNodesExpanded() const { return nodesExpanded; }
 	virtual uint64_t GetNodesTouched() const { return nodesTouched; }
 	virtual void LogFinalStats(StatCollection *s)
@@ -96,6 +108,7 @@
 		s->AddStat("TotalLearning", GetName(),fAmountLearned);
 		s->AddStat("MinInitial", GetName(),minInitialHeuristic);
 		s->AddStat("MaxLater", GetName(),maxLaterHeuristic);
+		s->AddStat("MaxStateLearning", GetName(), GetMaxStateLearning());
 	}

 	double GetAmountLearned() { return fAmountLearned; }


Fix ret code in pk_sign.c

Fix ret code in pk_sign.c

--- programs/pkey/pk_sign.c
+++ programs/pkey/pk_sign.c
@@ -30,9 +30,11 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_snprintf   snprintf
-#define mbedtls_printf     printf
-#endif
+#define mbedtls_snprintf        snprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXTI_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */

 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \
@@ -61,6 +63,7 @@
 {
     FILE *f;
     int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_pk_context pk;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -134,14 +137,12 @@

     if( ( f = fopen( filename, "wb+" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not create %s\n\n", filename );
         goto exit;
     }

     if( fwrite( buf, 1, olen, f ) != olen )
     {
-        ret = 1;
         mbedtls_printf( "failed\n  ! fwrite failed\n\n" );
         fclose( f );
         goto exit;
@@ -151,13 +152,15 @@

     mbedtls_printf( "\n  . Done (created \"%s\")\n\n", filename );

+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_pk_free( &pk );
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );

 #if defined(MBEDTLS_ERROR_C)
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
@@ -169,7 +172,7 @@
     fflush( stdout ); getchar();
 #endif

-    return( ret ? EXIT_FAILURE : EXIT_SUCCESS );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&


added -bbox option, like psubmit.c

added -bbox option, like psubmit.c

--- progs/spheres/spheres.c
+++ progs/spheres/spheres.c
@@ -52,6 +52,7 @@
 	int numTris;
 	int maxFrames;
 	int useVBO;
+	int useBBox;

 	/* derived */
 	float theta, zPos, radius;
@@ -71,6 +72,7 @@
 	GLuint VertexBufferObj;
 	GLuint ElementBufferObj;
 	GLuint DisplayList;
+	GLfloat Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
 } TriangleMesh;

@@ -281,6 +283,10 @@
 	glBindBufferARB_ptr(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 #endif

+	/* set bounds */
+	mesh->Xmin = mesh->Ymin = mesh->Zmin = -radius;
+	mesh->Xmax = mesh->Ymax = mesh->Zmax = +radius;
+
 	return mesh;
 }

@@ -358,8 +364,8 @@
 			glEnable(GL_VERTEX_ARRAY);
 			glEnable(GL_NORMAL_ARRAY);
 			first = 0;
-		}
-		glBindBufferARB_ptr(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->ElementBufferObj);
+			glBindBufferARB_ptr(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->ElementBufferObj);
+		}
 		if (mesh->NumIndices <= 65535)
 			glDrawRangeElements_ptr(GL_TRIANGLE_STRIP, 0, mesh->NumIndices - 1,
 															mesh->NumIndices, GL_UNSIGNED_SHORT, 0);
@@ -387,6 +393,35 @@
 }

+static void
+DrawMeshBBox(const TriangleMesh *mesh)
+{
+	glColor3f(1.0F, 1.0F, 1.0F);
+	glBegin(GL_LINE_LOOP);
+	glVertex3f(mesh->Xmin, mesh->Ymin, mesh->Zmin);
+	glVertex3f(mesh->Xmax, mesh->Ymin, mesh->Zmin);
+	glVertex3f(mesh->Xmax, mesh->Ymax, mesh->Zmin);
+	glVertex3f(mesh->Xmin, mesh->Ymax, mesh->Zmin);
+	glEnd();
+	glBegin(GL_LINE_LOOP);
+	glVertex3f(mesh->Xmin, mesh->Ymin, mesh->Zmax);
+	glVertex3f(mesh->Xmax, mesh->Ymin, mesh->Zmax);
+	glVertex3f(mesh->Xmax, mesh->Ymax, mesh->Zmax);
+	glVertex3f(mesh->Xmin, mesh->Ymax, mesh->Zmax);
+	glEnd();
+	glBegin(GL_LINES);
+	glVertex3f(mesh->Xmin, mesh->Ymin, mesh->Zmin);
+	glVertex3f(mesh->Xmin, mesh->Ymin, mesh->Zmax);
+	glVertex3f(mesh->Xmax, mesh->Ymin, mesh->Zmin);
+	glVertex3f(mesh->Xmax, mesh->Ymin, mesh->Zmax);
+	glVertex3f(mesh->Xmax, mesh->Ymax, mesh->Zmin);
+	glVertex3f(mesh->Xmax, mesh->Ymax, mesh->Zmax);
+	glVertex3f(mesh->Xmin, mesh->Ymax, mesh->Zmin);
+	glVertex3f(mesh->Xmin, mesh->Ymax, mesh->Zmax);
+	glEnd();
+}
+
+
 static TriangleMesh *
 MakeDemoMesh(const Options *options)
 {
@@ -435,6 +470,19 @@
 			glPushMatrix();
 				glRotatef(i * options->theta, 0.0f, 0.0f, 1.0f);
 				glTranslatef(0.65f, 0.0f, options->zPos);
+#if USE_CHROMIUM
+				if (options->useBBox) {
+					GLfloat bbox[6];
+					bbox[0] = mesh->Xmin;
+					bbox[1] = mesh->Ymin;
+					bbox[2] = mesh->Zmin;
+					bbox[3] = mesh->Xmax;
+					bbox[4] = mesh->Ymax;
+					bbox[5] = mesh->Zmax;
+					glChromiumParametervCR_ptr(GL_OBJECT_BBOX_CR, GL_FLOAT, 6, bbox);
+					DrawMeshBBox(mesh);
+				}
+#endif
 				tris += DrawMesh(mesh, mode);
 			glPopMatrix();
 		}
@@ -532,6 +580,7 @@
 	options->numTris = 12000;
 	options->maxFrames = 1000/* * 1000 * 1000*/;
 	options->useVBO = 1;
+	options->useBBox = 0;

 	for (i = 1 ; i < argc ; i++)
 	{
@@ -610,6 +659,10 @@
 		else if (!strcmp( argv[i], "-d" ))
 		{
 			DrawingMode = DRAW_DISPLAY_LIST;
+		}
+		else if (!strcmp( argv[i], "-bbox" ))
+		{
+			options->useBBox = 1;
 		}
 		else if (!strcmp( argv[i], "-h" ) || !strcmp(argv[i], "--help"))
 		{


Portability fixes.

Portability fixes.

--- lib/libarchive/archive.h
+++ lib/libarchive/archive.h
@@ -35,12 +35,16 @@
  * this header!  If you must conditionalize, use predefined compiler and/or
  * platform macros.
  */
+#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
+# define __LA_STDINT_H <stdint.h>
+#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__)
+# define __LA_STDINT_H <inttypes.h>
+#endif

 #include <sys/stat.h>
 #include <sys/types.h>  /* Linux requires this for off_t */
-#if !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX)
-/* Header unavailable on Watcom C or MS Visual C++ or SFU. */
-#include <inttypes.h> /* int64_t, etc. */
+#ifdef __LA_STDINT_H
+# include __LA_STDINT_H /* int64_t, etc. */
 #endif
 #include <stdio.h> /* For FILE * */

@@ -53,8 +57,13 @@
 # else
 #  define	__LA_SSIZE_T	long
 # endif
-#define	__LA_UID_T	unsigned int
-#define	__LA_GID_T	unsigned int
+# if defined(__BORLANDC__)
+#  define	__LA_UID_T	uid_t
+#  define	__LA_GID_T	gid_t
+# else
+#  define	__LA_UID_T	short
+#  define	__LA_GID_T	short
+# endif
 #else
 #include <unistd.h>  /* ssize_t, uid_t, and gid_t */
 #define	__LA_INT64_T	int64_t


[CpmlPrimitive] Avoid redundant code in cpml_primitive_reset()

Use cpml_primitive_from_segment() instead of duplicating the code, these
functions do the same job.

--- cpml/cpml-primitive.c
+++ cpml/cpml-primitive.c
@@ -122,8 +122,7 @@
 void
 cpml_primitive_reset(CpmlPrimitive *primitive)
 {
-    primitive->org = &primitive->segment->data[1];
-    primitive->data = primitive->segment->data + 2;
+    cpml_primitive_from_segment(primitive, primitive->segment);
 }

 /**


Fix a very rare error condition:  The code to free VM back to the kernel as done after a quasi-recursive call to free() had modified what we thought we knew about the last chunk of pages. This bug manifested itself when I did a "make obj" from src/usr.sbin/lpr, then make would coredump in the lpd directory.

--- lib/libc/stdlib/malloc.c
+++ lib/libc/stdlib/malloc.c
@@ -6,7 +6,7 @@
  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
  * ----------------------------------------------------------------------------
  *
- * $Id: malloc.c,v 1.10 1996/01/22 00:01:44 julian Exp $
+ * $Id: malloc.c,v 1.11 1996/07/03 05:03:07 phk Exp $
  *
  */

@@ -942,7 +942,7 @@
 free_pages(void *ptr, int index, struct pginfo *info)
 {
     int i;
-    struct pgfree *pf,*pt;
+    struct pgfree *pf,*pt=0;
     u_long l;
     void *tail;

@@ -1013,7 +1013,6 @@
 		pf->next = pt->next;
 		if (pf->next)
 		    pf->next->prev = pf;
-		free(pt);
 	    }
 	} else if (pf->page == tail) {
 	    /* Prepend to entry */
@@ -1055,6 +1054,8 @@

 	/* XXX: We could realloc/shrink the pagedir here I guess. */
     }
+    if (pt)
+	free(pt);
 }

 /*


[CpmlPrimitive] Updated documentation

[CpmlPrimitive] Updated documentation

Corrected misleading docblock of cpml_primitive_put_intersections().

--- cpml/cpml-primitive.c
+++ cpml/cpml-primitive.c
@@ -384,11 +384,6 @@
  *
  * Gets the number of points required to identify the @type primitive.
  *
- * <note><para>
- * This function is primitive dependent, that is every primitive has
- * its own implementation.
- * </para></note>
- *
  * Returns: the number of points or %0 on errors
  **/
 size_t
@@ -540,26 +535,21 @@
  * Finds the intersection points between the given primitives and
  * returns the result in @dest. The size of @dest should be enough
  * to store @n_dest #CpmlPair. The maximum number of intersections
- * is dependent from the type of the primitive involved in the
+ * is dependent on the type of the primitive involved in the
  * operation. If there are at least one Bézier curve involved, up to
- * 4 intersections could be returned. Otherwise, if there is an arc
- * the intersections will be 2 at maximum. For line line primitives,
- * there is only 1 point (or obviously 0 if the lines do not intersect).
+ * %4 intersections could be returned. Otherwise, if there is an arc
+ * the intersections will be %2 at maximum. For line primitives, there
+ * is only %1 point (or %0 if the lines are parallel).
  *
  * <note>
  * <para>
- * This function is primitive dependent: every new primitive must
- * expose API to get intersections with any other primitive type
- * (excluding #CPML_CLOSE, as it is converted to a line primitive).
- * </para>
- * <para>
- * The convention used by CPML is that a primitive should
- * expose only intersection APIs dealing with lower complexity
- * primitives. This is required to avoid double functions:
- * you will have only a cpml_curve_put_intersections_with_line()
- * function, not a cpml_line_put_intersections_with_curve(), as
- * the latter is easily reproduced by calling the former with
- * @primitive2 and @primitive swapped.
+ * The convention used by the CPML library is that a primitive should
+ * implement only the intersection algorithms with lower degree
+ * primitives. This is required to avoid code duplication: intersection
+ * between arc and Bézier curves must be implemented by #CPML_CURVE and
+ * intersection between lines and arcs must be implemented by #CPML_ARC.
+ * cpml_primitive_put_intersections() will take care of swapping the
+ * arguments if they are not properly ordered.
  * </para>
  * </note>
  *


Remove the run promotion/demotion machinery.  Replace it with red-black
trees that track all non-full runs for each bin.  Use the red-black
trees to be able to guarantee that each new allocation is placed in the
lowest address available in any non-full run.  This change completes the
transition to allocating from low addresses in order to reduce the
retention of sparsely used chunks.

If the run in current use by a bin becomes empty, deallocate the run
rather than retaining it for later use.  The previous behavior had the
tendency to spread empty runs across multiple chunks, thus preventing
the release of chunks that were completely unused.

Generalize base_chunk_alloc() (and rename it to base_pages_alloc()) to
handle allocation sizes larger than the chunk size, so that it is
possible to support chunk sizes that are smaller than an arena object.

Reduce the minimum chunk size from 64kB to 8kB.

Optimize tracking of addresses for deleted chunks.

Fix a statistics bug for huge allocations.

--- lib/libc/stdlib/malloc.c
+++ lib/libc/stdlib/malloc.c
@@ -38,10 +38,9 @@
  *   + Cache line sharing between arenas is avoided for internal data
  *     structures.
  *
- *   + Memory is managed in chunks and runs (chunks can be split into runs using
- *     a binary buddy scheme), rather than as individual pages.  This provides
- *     a constant-time mechanism for associating allocations with particular
- *     arenas.
+ *   + Memory is managed in chunks and runs (chunks can be split into runs),
+ *     rather than as individual pages.  This provides a constant-time
+ *     mechanism for associating allocations with particular arenas.
  *
  * Allocation requests are rounded up to the nearest size class, and no record
  * of the original request size is maintained.  Allocations are broken into
@@ -94,85 +93,6 @@
  */

 /*
- *******************************************************************************
- *
- * Ring macros.
- *
- *******************************************************************************
- */
-
-/* Ring definitions. */
-#define	qr(a_type) struct {						\
-	a_type *qre_next;						\
-	a_type *qre_prev;						\
-}
-
-#define	qr_initializer {NULL, NULL}
-
-/* Ring functions. */
-#define	qr_new(a_qr, a_field) do {					\
-	(a_qr)->a_field.qre_next = (a_qr);				\
-	(a_qr)->a_field.qre_prev = (a_qr);				\
-} while (0)
-
-#define	qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next)
-
-#define	qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev)
-
-#define	qr_before_insert(a_qrelm, a_qr, a_field) do {			\
-	(a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev;		\
-	(a_qr)->a_field.qre_next = (a_qrelm);				\
-	(a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr);		\
-	(a_qrelm)->a_field.qre_prev = (a_qr);				\
-} while (0)
-
-#define	qr_after_insert(a_qrelm, a_qr, a_field) do {			\
-	(a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next;		\
-	(a_qr)->a_field.qre_prev = (a_qrelm);				\
-	(a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr);		\
-	(a_qrelm)->a_field.qre_next = (a_qr);				\
-} while (0)
-
-#define	qr_meld(a_qr_a, a_qr_b, a_type, a_field) do {			\
-	a_type *t;							\
-	(a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b);	\
-	(a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a);	\
-	t = (a_qr_a)->a_field.qre_prev;					\
-	(a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev;	\
-	(a_qr_b)->a_field.qre_prev = t;					\
-} while (0)
-
-/*
- * qr_meld() and qr_split() are functionally equivalent, so there's no need to
- * have two copies of the code.
- */
-#define	qr_split(a_qr_a, a_qr_b, a_type, a_field)			\
-	qr_meld((a_qr_a), (a_qr_b), a_type, a_field)
-
-#define	qr_remove(a_qr, a_field) do {					\
-	(a_qr)->a_field.qre_prev->a_field.qre_next			\
-	    = (a_qr)->a_field.qre_next;					\
-	(a_qr)->a_field.qre_next->a_field.qre_prev			\
-	    = (a_qr)->a_field.qre_prev;					\
-	(a_qr)->a_field.qre_next = (a_qr);				\
-	(a_qr)->a_field.qre_prev = (a_qr);				\
-} while (0)
-
-#define	qr_foreach(var, a_qr, a_field)					\
-	for ((var) = (a_qr);						\
-	    (var) != NULL;						\
-	    (var) = (((var)->a_field.qre_next != (a_qr))		\
-	    ? (var)->a_field.qre_next : NULL))
-
-#define	qr_reverse_foreach(var, a_qr, a_field)				\
-	for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL;	\
-	    (var) != NULL;						\
-	    (var) = (((var) != (a_qr))					\
-	    ? (var)->a_field.qre_prev : NULL))
-
-/******************************************************************************/
-
-/*
  * MALLOC_PRODUCTION disables assertions and statistics gathering.  It also
  * defaults the A and J runtime options to off.  These settings are appropriate
  * for production systems.
@@ -331,7 +251,7 @@
 #define RUN_MAX_OVRHD_RELAX	1.5

 /* Put a cap on small object run size.  This overrides RUN_MAX_OVRHD. */
-#define RUN_MAX_SMALL_2POW	16
+#define RUN_MAX_SMALL_2POW	15
 #define RUN_MAX_SMALL		(1 << RUN_MAX_SMALL_2POW)

 /******************************************************************************/
@@ -369,10 +289,10 @@
 	uint64_t	nruns;

 	/*
-	 * Total number of run promotions/demotions for this bin's size class.
+	 * Total number of runs reused by extracting them from the runs tree for
+	 * this bin's size class.
 	 */
-	uint64_t	npromote;
-	uint64_t	ndemote;
+	uint64_t	reruns;

 	/* High-water mark for this bin. */
 	unsigned long	highruns;
@@ -505,8 +425,8 @@

 typedef struct arena_run_s arena_run_t;
 struct arena_run_s {
-	/* Linkage for run rings. */
-	qr(arena_run_t)	link;
+	/* Linkage for run trees. */
+	RB_ENTRY(arena_run_s) link;

 #ifdef MALLOC_DEBUG
 	uint32_t	magic;
@@ -522,44 +442,11 @@
 	/* Number of free regions in run. */
 	unsigned	nfree;

-	/*
-	 * Current quartile for this run, one of: {RUN_QINIT, RUN_Q0, RUN_25,
-	 * RUN_Q50, RUN_Q75, RUN_Q100}.
-	 */
-#define RUN_QINIT	0
-#define RUN_Q0		1
-#define RUN_Q25		2
-#define RUN_Q50		3
-#define RUN_Q75		4
-#define RUN_Q100	5
-	unsigned	quartile;
-
-	/*
-	 * Limits on the number of free regions for the fullness quartile this
-	 * run is currently in.  If nfree goes outside these limits, the run
-	 * is moved to a different fullness quartile.
-	 */
-	unsigned	free_max;
-	unsigned	free_min;
-
 	/* Bitmask of in-use regions (0: in use, 1: free). */
 	unsigned	regs_mask[1]; /* Dynamically sized. */
 };
-
-/* Used for run ring headers, where the run isn't actually used. */
-typedef struct arena_run_link_s arena_run_link_t;
-struct arena_run_link_s {
-	/* Linkage for run rings. */
-	qr(arena_run_t)	link;
-};
-
-/* Avoid pointer aliasing issues. */
-static inline arena_run_t *
-arena_bin_link(void *ptr)
-{
-
-	return ((arena_run_t *)ptr);
-}
+typedef struct arena_run_tree_s arena_run_tree_t;
+RB_HEAD(arena_run_tree_s, arena_run_s);

 struct arena_bin_s {
 	/*
@@ -569,38 +456,13 @@
 	arena_run_t	*runcur;

 	/*
-	 * Links into rings of runs, of various fullnesses (names indicate
-	 * approximate lower bounds).  A new run conceptually starts off in
-	 * runsinit, and it isn't inserted into the runs0 ring until it
-	 * reaches 25% full (hysteresis mechanism).  For the run to be moved
-	 * again, it must become either empty or 50% full.  Thus, each ring
-	 * contains runs that are within 50% above the advertised fullness for
-	 * the ring.  This provides a low-overhead mechanism for segregating
-	 * runs into approximate fullness classes.
-	 *
-	 * Conceptually, there is a runs100 that contains completely full runs.
-	 * Since we don't need to search for these runs though, no runs100 ring
-	 * is actually maintained.
-	 *
-	 * These rings are useful when looking for an existing run to use when
-	 * runcur is no longer usable.  We look for usable runs in the
-	 * following order:
-	 *
-	 *   1) runs50
-	 *   2) runs25
-	 *   3) runs0
-	 *   4) runs75
-	 *
-	 * runs75 isn't a good place to look, because it contains runs that may
-	 * be nearly completely full.  Still, we look there as a last resort in
-	 * order to avoid allocating a new run if at all possible.
+	 * Tree of non-full runs.  This tree is used when looking for an
+	 * existing run when runcur is no longer usable.  We choose the
+	 * non-full run that is lowest in memory; this policy tends to keep
+	 * objects packed well, and it can also help reduce the number of
+	 * almost-empty chunks.
 	 */
-	/* arena_run_link_t	runsinit;   0% <= fullness <   25% */
-	arena_run_link_t	runs0;  /*  0% <  fullness <   50% */
-	arena_run_link_t	runs25; /* 25% <  fullness <   75% */
-	arena_run_link_t	runs50; /* 50% <  fullness <  100% */
-	arena_run_link_t	runs75; /* 75% <  fullness <  100% */
-	/* arena_run_link_t	runs100;          fullness == 100% */
+	arena_run_tree_t runs;

 	/* Size of regions in a run for this bin's size class. */
 	size_t		reg_size;
@@ -727,7 +589,7 @@
  */
 /*
  * Protects sbrk() calls.  This must be separate from chunks_mtx, since
- * base_chunk_alloc() also uses sbrk(), but cannot lock chunks_mtx (doing so
+ * base_pages_alloc() also uses sbrk(), but cannot lock chunks_mtx (doing so
  * could cause recursive lock acquisition).
  */
 static malloc_mutex_t	brk_mtx;
@@ -740,10 +602,7 @@
 #endif

 #ifdef MALLOC_STATS
-/*
- * Byte counters for allocated/mapped space used by the chunks in the huge
- * allocations tree.
- */
+/* Huge allocation statistics. */
 static uint64_t		huge_nmalloc;
 static uint64_t		huge_ndalloc;
 static size_t		huge_allocated;
@@ -761,13 +620,13 @@
  */

 /*
- * Current chunk that is being used for internal memory allocations.  This
- * chunk is carved up in cacheline-size quanta, so that there is no chance of
+ * Current pages that are being used for internal memory allocations.  These
+ * pages are carved up in cacheline-size quanta, so that there is no chance of
  * false cache line sharing.
  */
-static void		*base_chunk;
+static void		*base_pages;
 static void		*base_next_addr;
-static void		*base_past_addr; /* Addr immediately past base_chunk. */
+static void		*base_past_addr; /* Addr immediately past base_pages. */
 static chunk_node_t	*base_chunk_nodes; /* LIFO cache of chunk nodes. */
 static malloc_mutex_t	base_mtx;
 #ifdef MALLOC_STATS
@@ -851,7 +710,7 @@
 static void	malloc_printf(const char *format, ...);
 #endif
 static char	*umax2s(uintmax_t x, char *s);
-static bool	base_chunk_alloc(size_t minsize);
+static bool	base_pages_alloc(size_t minsize);
 static void	*base_alloc(size_t size);
 static chunk_node_t *base_chunk_node_alloc(void);
 static void	base_chunk_node_dealloc(chunk_node_t *node);
@@ -868,10 +727,6 @@
 static void	arena_run_split(arena_t *arena, arena_run_t *run, size_t size);
 static arena_chunk_t *arena_chunk_alloc(arena_t *arena);
 static void	arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
-static void	arena_bin_run_promote(arena_t *arena, arena_bin_t *bin,
-    arena_run_t *run);
-static void	arena_bin_run_demote(arena_t *arena, arena_bin_t *bin,
-    arena_run_t *run);
 static arena_run_t *arena_run_alloc(arena_t *arena, size_t size);
 static void	arena_run_dalloc(arena_t *arena, arena_run_t *run, size_t size);
 static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
@@ -1039,19 +894,21 @@
 /******************************************************************************/

 static bool
-base_chunk_alloc(size_t minsize)
-{
-
-	assert(minsize <= chunksize);
+base_pages_alloc(size_t minsize)
+{
+	size_t csize;

 #ifdef USE_BRK
 	/*
-	 * Do special brk allocation here, since the base chunk doesn't really
-	 * need to be chunk-aligned.
+	 * Do special brk allocation here, since base allocations don't need to
+	 * be chunk-aligned.
 	 */
 	if (brk_prev != (void *)-1) {
 		void *brk_cur;
 		intptr_t incr;
+
+		if (minsize != 0)
+			csize = CHUNK_CEILING(minsize);

 		malloc_mutex_lock(&brk_mtx);
 		do {
@@ -1066,15 +923,15 @@
 			incr = (intptr_t)chunksize
 			    - (intptr_t)CHUNK_ADDR2OFFSET(brk_cur);
 			if (incr < minsize)
-				incr += chunksize;
+				incr += csize;

 			brk_prev = sbrk(incr);
 			if (brk_prev == brk_cur) {
 				/* Success. */
 				malloc_mutex_unlock(&brk_mtx);
-				base_chunk = brk_cur;
-				base_next_addr = base_chunk;
-				base_past_addr = (void *)((uintptr_t)base_chunk
+				base_pages = brk_cur;
+				base_next_addr = base_pages;
+				base_past_addr = (void *)((uintptr_t)base_pages
 				    + incr);
 #ifdef MALLOC_STATS
 				base_mapped += incr;
@@ -1084,19 +941,23 @@
 		} while (brk_prev != (void *)-1);
 		malloc_mutex_unlock(&brk_mtx);
 	}
-#endif
-
-	/*
-	 * Don't worry about chunk alignment here, since base_chunk doesn't
-	 * really need to be aligned.
-	 */
-	base_chunk = pages_map(NULL, chunksize);
-	if (base_chunk == NULL)
+	if (minsize == 0) {
+		/*
+		 * Failure during initialization doesn't matter, so avoid
+		 * falling through to the mmap-based page mapping code.
+		 */
 		return (true);
-	base_next_addr = base_chunk;
-	base_past_addr = (void *)((uintptr_t)base_chunk + chunksize);
+	}
+#endif
+	assert(minsize != 0);
+	csize = PAGE_CEILING(minsize);
+	base_pages = pages_map(NULL, csize);
+	if (base_pages == NULL)
+		return (true);
+	base_next_addr = base_pages;
+	base_past_addr = (void *)((uintptr_t)base_pages + csize);
 #ifdef MALLOC_STATS
-	base_mapped += chunksize;
+	base_mapped += csize;
 #endif
 	return (false);
 }
@@ -1112,13 +973,9 @@

 	malloc_mutex_lock(&base_mtx);

-	/*
-	 * Make sure there's enough space for the allocation.
-	 * base_chunk_alloc() does not guarantee that a newly allocated chunk
-	 * is >= size, so loop here, rather than only trying once.
-	 */
-	while ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
-		if (base_chunk_alloc(csize)) {
+	/* Make sure there's enough space for the allocation. */
+	if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
+		if (base_pages_alloc(csize)) {
 			ret = NULL;
 			goto RETURN;
 		}
@@ -1184,8 +1041,8 @@
 	    arena->stats.nmalloc_small + arena->stats.nmalloc_large,
 	    arena->stats.ndalloc_small + arena->stats.ndalloc_large);

-	malloc_printf("bins:     bin   size regs pgs  requests newruns "
-	    "maxruns curruns promote  demote\n");
+	malloc_printf("bins:     bin   size regs pgs  requests   newruns"
+	    "    reruns maxruns curruns\n");
 	for (i = 0, gap_start = -1; i < ntbins + nqbins + nsbins; i++) {
 		if (arena->bins[i].stats.nrequests == 0) {
 			if (gap_start == -1)
@@ -1203,8 +1060,8 @@
 				gap_start = -1;
 			}
 			malloc_printf(
-			    "%13u %1s %4u %4u %3u %9llu %7llu"
-			    " %7lu %7lu %7llu %7llu\n",
+			    "%13u %1s %4u %4u %3u %9llu %9llu"
+			    " %9llu %7lu %7lu\n",
 			    i,
 			    i < ntbins ? "T" : i < ntbins + nqbins ? "Q" : "S",
 			    arena->bins[i].reg_size,
@@ -1212,10 +1069,9 @@
 			    arena->bins[i].run_size >> pagesize_2pow,
 			    arena->bins[i].stats.nrequests,
 			    arena->bins[i].stats.nruns,
+			    arena->bins[i].stats.reruns,
 			    arena->bins[i].stats.highruns,
-			    arena->bins[i].stats.curruns,
-			    arena->bins[i].stats.npromote,
-			    arena->bins[i].stats.ndemote);
+			    arena->bins[i].stats.curruns);
 		}
 	}
 	if (gap_start != -1) {
@@ -1427,6 +1283,24 @@
 	/* All strategies for allocation failed. */
 	ret = NULL;
 RETURN:
+	if (ret != NULL) {
+		chunk_node_t key;
+		/*
+		 * Clean out any entries in old_chunks that overlap with the
+		 * memory we just allocated.
+		 */
+		key.chunk = ret;
+		tchunk = RB_NFIND(chunk_tree_s, &old_chunks, &key);
+		while (tchunk != NULL
+		    && (uintptr_t)tchunk->chunk >= (uintptr_t)ret
+		    && (uintptr_t)tchunk->chunk < (uintptr_t)ret + size) {
+			delchunk = tchunk;
+			tchunk = RB_NEXT(chunk_tree_s, &old_chunks, delchunk);
+			RB_REMOVE(chunk_tree_s, &old_chunks, delchunk);
+			base_chunk_node_dealloc(delchunk);
+		}
+
+	}
 #ifdef MALLOC_STATS
 	if (ret != NULL) {
 		stats_chunks.nchunks += (size / chunksize);
@@ -1444,8 +1318,6 @@
 static void
 chunk_dealloc(void *chunk, size_t size)
 {
-	size_t offset;
-	chunk_node_t key;
 	chunk_node_t *node;

 	assert(chunk != NULL);
@@ -1481,40 +1353,52 @@
 				    - (intptr_t)size);
 				brk_max = brk_prev;
 			}
-			goto RETURN;
-		} else
+		} else {
+			size_t offset;
+
 			malloc_mutex_unlock(&brk_mtx);
 			madvise(chunk, size, MADV_FREE);
-	} else
+
+			/*
+			 * Iteratively create records of each chunk-sized
+			 * memory region that 'chunk' is comprised of, so that
+			 * the address range can be recycled if memory usage
+			 * increases later on.
+			 */
+			for (offset = 0; offset < size; offset += chunksize) {
+				node = base_chunk_node_alloc();
+				if (node == NULL)
+					break;
+
+				node->chunk = (void *)((uintptr_t)chunk
+				    + (uintptr_t)offset);
+				node->size = chunksize;
+				RB_INSERT(chunk_tree_s, &old_chunks, node);
+			}
+		}
+	} else {
 #endif
 		pages_unmap(chunk, size);

-	/*
-	 * Iteratively create records of each chunk-sized memory region that
-	 * 'chunk' is comprised of, so that the address range can be recycled
-	 * if memory usage increases later on.
-	 */
-	for (offset = 0; offset < size; offset += chunksize) {
 		/*
-		 * It is possible for chunk to overlap existing entries in
-		 * old_chunks if it is a huge allocation, so take care to not
-		 * leak tree nodes.
+		 * Make a record of the chunk's address, so that the address
+		 * range can be recycled if memory usage increases later on.
+		 * Don't bother to create entries if (size > chunksize), since
+		 * doing so could cause scalability issues for truly gargantuan
+		 * objects (many gigabytes or larger).
 		 */
-		key.chunk = (void *)((uintptr_t)chunk + (uintptr_t)offset);
-		if (RB_FIND(chunk_tree_s, &old_chunks, &key) == NULL) {
+		if (size == chunksize) {
 			node = base_chunk_node_alloc();
-			if (node == NULL)
-				break;
-
-			node->chunk = key.chunk;
-			node->size = chunksize;
-			RB_INSERT(chunk_tree_s, &old_chunks, node);
+			if (node != NULL) {
+				node->chunk = (void *)(uintptr_t)chunk;
+				node->size = chunksize;
+				RB_INSERT(chunk_tree_s, &old_chunks, node);
+			}
 		}
-	}
-
 #ifdef USE_BRK
-RETURN:
-#endif
+	}
+#endif
+
 #ifdef MALLOC_STATS
 	stats_chunks.curchunks -= (size / chunksize);
 #endif
@@ -1656,6 +1540,24 @@
 /* Generate red-black tree code for arena chunks. */
 RB_GENERATE_STATIC(arena_chunk_tree_s, arena_chunk_s, link, arena_chunk_comp);

+static inline int
+arena_run_comp(arena_run_t *a, arena_run_t *b)
+{
+
+	assert(a != NULL);
+	assert(b != NULL);
+
+	if ((uintptr_t)a < (uintptr_t)b)
+		return (-1);
+	else if (a == b)
+		return (0);
+	else
+		return (1);
+}
+
+/* Generate red-black tree code for arena runs. */
+RB_GENERATE_STATIC(arena_run_tree_s, arena_run_s, link, arena_run_comp);
+
 static inline void *
 arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin)
 {
@@ -1663,28 +1565,51 @@
 	unsigned i, mask, bit, regind;

 	assert(run->magic == ARENA_RUN_MAGIC);
-
-	for (i = run->regs_minelm; i < bin->regs_mask_nelms; i++) {
+	assert(run->regs_minelm < bin->regs_mask_nelms);
+
+	/*
+	 * Move the first check outside the loop, so that run->regs_minelm can
+	 * be updated unconditionally, without the possibility of updating it
+	 * multiple times.
+	 */
+	i = run->regs_minelm;
+	mask = run->regs_mask[i];
+	if (mask != 0) {
+		/* Usable allocation found. */
+		bit = ffs((int)mask) - 1;
+
+		regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
+		ret = (void *)(((uintptr_t)run) + bin->reg0_offset
+		    + (bin->reg_size * regind));
+
+		/* Clear bit. */
+		mask ^= (1 << bit);
+		run->regs_mask[i] = mask;
+
+		return (ret);
+	}
+
+	for (i++; i < bin->regs_mask_nelms; i++) {
 		mask = run->regs_mask[i];
 		if (mask != 0) {
 			/* Usable allocation found. */
 			bit = ffs((int)mask) - 1;

 			regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
-			ret = (void *)&((char *)run)[bin->reg0_offset
-			    + (bin->reg_size * regind)];
+			ret = (void *)(((uintptr_t)run) + bin->reg0_offset
+			    + (bin->reg_size * regind));

 			/* Clear bit. */
 			mask ^= (1 << bit);
 			run->regs_mask[i] = mask;

-			return (ret);
-		} else {
 			/*
 			 * Make a note that nothing before this element
 			 * contains a free region.
 			 */
-			run->regs_minelm = i + 1;
+			run->regs_minelm = i; /* Low payoff: + (mask == 0); */
+
+			return (ret);
 		}
 	}
 	/* Not reached. */
@@ -1899,155 +1824,6 @@
 #ifdef MALLOC_STATS
 		arena->stats.mapped -= chunksize;
 #endif
-	}
-}
-
-static void
-arena_bin_run_promote(arena_t *arena, arena_bin_t *bin, arena_run_t *run)
-{
-
-	assert(bin == run->bin);
-
-	/* Promote. */
-	assert(run->free_min > run->nfree);
-	assert(run->quartile < RUN_Q100);
-	run->quartile++;
-#ifdef MALLOC_STATS
-	bin->stats.npromote++;
-#endif
-
-	/* Re-file run. */
-	switch (run->quartile) {
-		case RUN_QINIT:
-			assert(0);
-			break;
-		case RUN_Q0:
-			qr_before_insert(arena_bin_link(&bin->runs0), run,
-			    link);
-			run->free_max = bin->nregs - 1;
-			run->free_min = (bin->nregs >> 1) + 1;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		case RUN_Q25:
-			qr_remove(run, link);
-			qr_before_insert(arena_bin_link(&bin->runs25), run,
-			    link);
-			run->free_max = ((bin->nregs >> 2) * 3) - 1;
-			run->free_min = (bin->nregs >> 2) + 1;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		case RUN_Q50:
-			qr_remove(run, link);
-			qr_before_insert(arena_bin_link(&bin->runs50), run,
-			    link);
-			run->free_max = (bin->nregs >> 1) - 1;
-			run->free_min = 1;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		case RUN_Q75:
-			/*
-			 * Skip RUN_Q75 during promotion from RUN_Q50.
-			 * Separate handling of RUN_Q75 and RUN_Q100 allows us
-			 * to keep completely full runs in RUN_Q100, thus
-			 * guaranteeing that runs in RUN_Q75 are only mostly
-			 * full.  This provides a method for avoiding a linear
-			 * search for non-full runs, which avoids some
-			 * pathological edge cases.
-			 */
-			run->quartile++;
-#ifdef MALLOC_STATS
-			/*
-			 * Count as a double promotion, in order to keep
-			 * promotions and demotions symmetric.
-			 */
-			bin->stats.npromote++;
-#endif
-			/* Fall through. */
-		case RUN_Q100:
-			qr_remove(run, link);
-			assert(bin->runcur == run);
-			bin->runcur = NULL;
-			run->free_max = 0;
-			run->free_min = 0;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		default:
-			assert(0);
-			break;
-	}
-}
-
-static void
-arena_bin_run_demote(arena_t *arena, arena_bin_t *bin, arena_run_t *run)
-{
-
-	assert(bin == run->bin);
-
-	/* Demote. */
-	assert(run->free_max < run->nfree);
-	assert(run->quartile > RUN_QINIT);
-	run->quartile--;
-#ifdef MALLOC_STATS
-	bin->stats.ndemote++;
-#endif
-
-	/* Re-file run. */
-	switch (run->quartile) {
-		case RUN_QINIT:
-			qr_remove(run, link);
-#ifdef MALLOC_STATS
-			bin->stats.curruns--;
-#endif
-			if (bin->runcur == run)
-				bin->runcur = NULL;
-#ifdef MALLOC_DEBUG
-			run->magic = 0;
-#endif
-			arena_run_dalloc(arena, run, bin->run_size);
-			break;
-		case RUN_Q0:
-			qr_remove(run, link);
-			qr_before_insert(arena_bin_link(&bin->runs0), run,
-			    link);
-			run->free_max = bin->nregs - 1;
-			run->free_min = (bin->nregs >> 1) + 1;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		case RUN_Q25:
-			qr_remove(run, link);
-			qr_before_insert(arena_bin_link(&bin->runs25), run,
-			    link);
-			run->free_max = ((bin->nregs >> 2) * 3) - 1;
-			run->free_min = (bin->nregs >> 2) + 1;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		case RUN_Q50:
-			qr_remove(run, link);
-			qr_before_insert(arena_bin_link(&bin->runs50), run,
-			    link);
-			run->free_max = (bin->nregs >> 1) - 1;
-			run->free_min = 1;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		case RUN_Q75:
-			qr_before_insert(arena_bin_link(&bin->runs75), run,
-			    link);
-			run->free_max = (bin->nregs >> 2) - 1;
-			run->free_min = 1;
-			assert(run->nfree <= run->free_max);
-			assert(run->nfree >= run->free_min);
-			break;
-		case RUN_Q100:
-		default:
-			assert(0);
-			break;
 	}
 }

@@ -2212,16 +1988,12 @@
 	unsigned i, remainder;

 	/* Look for a usable run. */
-	if ((run = qr_next(arena_bin_link(&bin->runs50), link))
-	    != arena_bin_link(&bin->runs50)
-	    || (run = qr_next(arena_bin_link(&bin->runs25), link))
-	    != arena_bin_link(&bin->runs25)
-	    || (run = qr_next(arena_bin_link(&bin->runs0), link))
-	    != arena_bin_link(&bin->runs0)
-	    || (run = qr_next(arena_bin_link(&bin->runs75), link))
-	    != arena_bin_link(&bin->runs75)) {
+	if ((run = RB_MIN(arena_run_tree_s, &bin->runs)) != NULL) {
 		/* run is guaranteed to have available space. */
-		qr_remove(run, link);
+		RB_REMOVE(arena_run_tree_s, &bin->runs, run);
+#ifdef MALLOC_STATS
+		bin->stats.reruns++;
+#endif
 		return (run);
 	}
 	/* No existing runs have any space available. */
@@ -2232,25 +2004,20 @@
 		return (NULL);

 	/* Initialize run internals. */
-	qr_new(run, link);
 	run->bin = bin;

 	for (i = 0; i < bin->regs_mask_nelms; i++)
 		run->regs_mask[i] = UINT_MAX;
-	remainder = bin->nregs % (1 << (SIZEOF_INT_2POW + 3));
+	remainder = bin->nregs & ((1 << (SIZEOF_INT_2POW + 3)) - 1);
 	if (remainder != 0) {
 		/* The last element has spare bits that need to be unset. */
 		run->regs_mask[i] = (UINT_MAX >> ((1 << (SIZEOF_INT_2POW + 3))
 		    - remainder));
-		i++;
 	}

 	run->regs_minelm = 0;

 	run->nfree = bin->nregs;
-	run->quartile = RUN_QINIT;
-	run->free_max = bin->nregs;
-	run->free_min = ((bin->nregs >> 2) * 3) + 1;
 #ifdef MALLOC_DEBUG
 	run->magic = ARENA_RUN_MAGIC;
 #endif
@@ -2276,10 +2043,6 @@
 	ret = arena_run_reg_alloc(run, bin);
 	assert(ret != NULL);
 	run->nfree--;
-	if (run->nfree < run->free_min) {
-		/* Promote run to higher fullness quartile. */
-		arena_bin_run_promote(arena, bin, run);
-	}

 	return (ret);
 }
@@ -2288,8 +2051,6 @@
 static void *
 arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
 {
-
-	assert(bin->runcur == NULL || bin->runcur->quartile == RUN_Q100);

 	bin->runcur = arena_bin_nonfull_run_get(arena, bin);
 	if (bin->runcur == NULL)
@@ -2429,7 +2190,7 @@
 		assert(size == bin->reg_size);

 		malloc_mutex_lock(&arena->mtx);
-		if ((run = bin->runcur) != NULL)
+		if ((run = bin->runcur) != NULL && run->nfree > 0)
 			ret = arena_bin_malloc_easy(arena, bin, run);
 		else
 			ret = arena_bin_malloc_hard(arena, bin);
@@ -2592,7 +2353,8 @@

 		pageind -= mapelm->pos;

-		run = (arena_run_t *)&((char *)chunk)[pageind << pagesize_2pow];
+		run = (arena_run_t *)((uintptr_t)chunk + (pageind <<
+		    pagesize_2pow));
 		assert(run->magic == ARENA_RUN_MAGIC);
 		ret = run->bin->reg_size;
 	} else
@@ -2643,9 +2405,9 @@
 	return (ret);
 IN_PLACE:
 	if (opt_junk && size < oldsize)
-		memset(&((char *)ptr)[size], 0x5a, oldsize - size);
+		memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
 	else if (opt_zero && size > oldsize)
-		memset(&((char *)ptr)[size], 0, size - oldsize);
+		memset((void *)((uintptr_t)ptr + size), 0, oldsize - size);
 	return (ptr);
 }

@@ -2673,7 +2435,8 @@

 		pageind -= mapelm->pos;

-		run = (arena_run_t *)&((char *)chunk)[pageind << pagesize_2pow];
+		run = (arena_run_t *)((uintptr_t)chunk + (pageind <<
+		    pagesize_2pow));
 		assert(run->magic == ARENA_RUN_MAGIC);
 		bin = run->bin;
 		size = bin->reg_size;
@@ -2684,9 +2447,44 @@
 		malloc_mutex_lock(&arena->mtx);
 		arena_run_reg_dalloc(run, bin, ptr, size);
 		run->nfree++;
-		if (run->nfree > run->free_max) {
-			/* Demote run to lower fullness quartile. */
-			arena_bin_run_demote(arena, bin, run);
+
+		if (run->nfree == bin->nregs) {
+			/* Deallocate run. */
+			if (run == bin->runcur)
+				bin->runcur = NULL;
+			else if (bin->nregs != 1) {
+				/*
+				 * This block's conditional is necessary because
+				 * if the run only contains one region, then it
+				 * never gets inserted into the non-full runs
+				 * tree.
+				 */
+				RB_REMOVE(arena_run_tree_s, &bin->runs, run);
+			}
+#ifdef MALLOC_DEBUG
+			run->magic = 0;
+#endif
+			arena_run_dalloc(arena, run, bin->run_size);
+#ifdef MALLOC_STATS
+			bin->stats.curruns--;
+#endif
+		} else if (run->nfree == 1 && run != bin->runcur) {
+			/*
+			 * Make sure that bin->runcur always refers to the
+			 * lowest non-full run, if one exists.
+			 */
+			if (bin->runcur == NULL)
+				bin->runcur = run;
+			else if ((uintptr_t)run < (uintptr_t)bin->runcur) {
+				/* Switch runcur. */
+				if (bin->runcur->nfree > 0) {
+					/* Insert runcur. */
+					RB_INSERT(arena_run_tree_s, &bin->runs,
+					    bin->runcur);
+				}
+				bin->runcur = run;
+			} else
+				RB_INSERT(arena_run_tree_s, &bin->runs, run);
 		}
 #ifdef MALLOC_STATS
 		arena->stats.allocated_small -= size;
@@ -2736,10 +2534,7 @@
 	for (i = 0; i < ntbins; i++) {
 		bin = &arena->bins[i];
 		bin->runcur = NULL;
-		qr_new(arena_bin_link(&bin->runs0), link);
-		qr_new(arena_bin_link(&bin->runs25), link);
-		qr_new(arena_bin_link(&bin->runs50), link);
-		qr_new(arena_bin_link(&bin->runs75), link);
+		RB_INIT(&bin->runs);

 		bin->reg_size = (1 << (TINY_MIN_2POW + i));

@@ -2754,10 +2549,7 @@
 	for (; i < ntbins + nqbins; i++) {
 		bin = &arena->bins[i];
 		bin->runcur = NULL;
-		qr_new(arena_bin_link(&bin->runs0), link);
-		qr_new(arena_bin_link(&bin->runs25), link);
-		qr_new(arena_bin_link(&bin->runs50), link);
-		qr_new(arena_bin_link(&bin->runs75), link);
+		RB_INIT(&bin->runs);

 		bin->reg_size = quantum * (i - ntbins + 1);

@@ -2773,10 +2565,7 @@
 	for (; i < ntbins + nqbins + nsbins; i++) {
 		bin = &arena->bins[i];
 		bin->runcur = NULL;
-		qr_new(arena_bin_link(&bin->runs0), link);
-		qr_new(arena_bin_link(&bin->runs25), link);
-		qr_new(arena_bin_link(&bin->runs50), link);
-		qr_new(arena_bin_link(&bin->runs75), link);
+		RB_INIT(&bin->runs);

 		bin->reg_size = (small_max << (i - (ntbins + nqbins) + 1));

@@ -2944,7 +2733,8 @@
 	malloc_mutex_lock(&chunks_mtx);
 	RB_INSERT(chunk_tree_s, &huge, node);
 #ifdef MALLOC_STATS
-	huge_allocated += size;
+	huge_nmalloc++;
+	huge_allocated += chunk_size;
 #endif
 	malloc_mutex_unlock(&chunks_mtx);

@@ -3006,7 +2796,6 @@
 	RB_REMOVE(chunk_tree_s, &huge, node);

 #ifdef MALLOC_STATS
-	/* Update counters. */
 	huge_ndalloc++;
 	huge_allocated -= node->size;
 #endif
@@ -3482,11 +3271,11 @@
 				break;
 			case 'k':
 				/*
-				 * Run fullness quartile limits don't have
-				 * enough resolution if there are too few
-				 * regions for the largest bin size classes.
+				 * Chunks always require at least one header
+				 * page, so chunks can never be smaller than
+				 * two pages.
 				 */
-				if (opt_chunk_2pow > pagesize_2pow + 4)
+				if (opt_chunk_2pow > pagesize_2pow + 1)
 					opt_chunk_2pow--;
 				break;
 			case 'K':
@@ -3647,7 +3436,7 @@
 	 * chunk-aligned.  Doing this before allocating any other chunks allows
 	 * the use of space that would otherwise be wasted.
 	 */
-	base_chunk_alloc(0);
+	base_pages_alloc(0);
 #endif
 	base_chunk_nodes = NULL;
 	malloc_mutex_init(&base_mtx);


Remove the triplicity in the public functions by vectoring them all
through a realloc like function.

Make the malloc_active variable a local static to this new function.

Don't warn about recursion more than once per base call.

constify malloc_func.

--- lib/libc/stdlib/malloc.c
+++ lib/libc/stdlib/malloc.c
@@ -201,9 +201,6 @@
 /* Set when initialization has been done */
 static unsigned malloc_started;

-/* Recusion flag for public interface. */
-static int malloc_active;
-
 /* Number of free pages we cache */
 static unsigned malloc_cache = 16;

@@ -274,7 +271,7 @@
 const char *_malloc_options;

 /* Name of the current public function */
-static char *malloc_func;
+static const char *malloc_func;

 /* Macro for mmap */
 #define MMAP(size) \
@@ -1094,83 +1091,40 @@
     return;
 }

-/*
- * These are the public exported interface routines.
- */
-
-
-void *
-malloc(size_t size)
+static void *
+pubrealloc(void *ptr, size_t size, const char *func)
 {
     void *r;
-
+    int err = 0;
+    static int malloc_active; /* Recusion flag for public interface. */
+
+    /*
+     * If a thread is inside our code with a functional lock held, and then
+     * catches a signal which calls us again, we would get a deadlock if the
+     * lock is not of a recursive type.
+     */
     _MALLOC_LOCK();
-    malloc_func = " in malloc():";
-    if (malloc_active++) {
-	wrtwarning("recursive call\n");
-        malloc_active--;
+    malloc_func = func;
+    if (malloc_active > 0) {
+	if (malloc_active == 1) {
+	    wrtwarning("recursive call\n");
+	    malloc_active = 2;
+	}
         _MALLOC_UNLOCK();
 	errno = EDOOFUS;
 	return (NULL);
-    }
-    if (malloc_sysv && !size)
-	r = NULL;
-    else if (!size)
-	r = ZEROSIZEPTR;
-    else
-	r = imalloc(size);
-    UTRACE(0, size, r);
-    malloc_active--;
-    _MALLOC_UNLOCK();
-    if (malloc_xmalloc && r == NULL)
-	wrterror("out of memory\n");
-    if (r == NULL)
-	errno = ENOMEM;
-    return (r);
-}
-
-void
-free(void *ptr)
-{
-    _MALLOC_LOCK();
-    malloc_func = " in free():";
-    if (malloc_active++) {
-	wrtwarning("recursive call\n");
-	malloc_active--;
-        _MALLOC_UNLOCK();
-	errno = EDOOFUS;
-	return;
-    }
-    if (ptr != ZEROSIZEPTR)
-	    ifree(ptr);
-    UTRACE(ptr, 0, 0);
-    malloc_active--;
-    _MALLOC_UNLOCK();
-    return;
-}
-
-void *
-realloc(void *ptr, size_t size)
-{
-    void *r;
-    int err = 0;
-
-    _MALLOC_LOCK();
-    malloc_func = " in realloc():";
-    if (malloc_active++) {
-	wrtwarning("recursive call\n");
-        malloc_active--;
-        _MALLOC_UNLOCK();
-	errno = EDOOFUS;
-	return (NULL);
-    }
+    }
+    malloc_active = 1;
+
     if (ptr == ZEROSIZEPTR)
 	ptr = NULL;
     if (malloc_sysv && !size) {
-	ifree(ptr);
-	r = 0;
+	if (ptr != NULL)
+	    ifree(ptr);
+	r = NULL;
     } else if (!size) {
-	ifree(ptr);
+	if (ptr != NULL)
+	    ifree(ptr);
 	r = ZEROSIZEPTR;
     } else if (ptr == NULL) {
 	r = imalloc(size);
@@ -1180,7 +1134,7 @@
 	err = (r == NULL);
     }
     UTRACE(ptr, size, r);
-    malloc_active--;
+    malloc_active = 0;
     _MALLOC_UNLOCK();
     if (malloc_xmalloc && err)
 	wrterror("out of memory\n");
@@ -1189,3 +1143,28 @@
     return (r);
 }

+/*
+ * These are the public exported interface routines.
+ */
+
+void *
+malloc(size_t size)
+{
+
+    return (pubrealloc(NULL, size, " in malloc():"));
+}
+
+void
+free(void *ptr)
+{
+
+    pubrealloc(ptr, 0, " in free():");
+}
+
+void *
+realloc(void *ptr, size_t size)
+{
+
+    return (pubrealloc(ptr, size, " in realloc():"));
+}
+


Handle zero size for posix_memalign. Return NULL or unique address
according to the 'V' option.

PR:	standards/138307
MFC after:	1 week

--- lib/libc/stdlib/malloc.c
+++ lib/libc/stdlib/malloc.c
@@ -5320,6 +5320,15 @@
 			goto RETURN;
 		}

+		if (size == 0) {
+			if (opt_sysv == false)
+				size = 1;
+			else {
+				result = NULL;
+				ret = 0;
+				goto RETURN;
+			}
+		}
 		result = ipalloc(alignment, size);
 	}