mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 05:38:39 +00:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
Vendored
+2
@@ -101,6 +101,8 @@ else:
|
||||
ASFLAGS += ['-no-integrated-as']
|
||||
elif CONFIG['FFI_TARGET'] == 'AARCH64':
|
||||
ffi_srcs = ('sysv.S', 'ffi.c')
|
||||
elif CONFIG['FFI_TARGET'] == 'LOONGARCH64':
|
||||
ffi_srcs = ('ffi.c', 'sysv.S')
|
||||
elif CONFIG['FFI_TARGET'] == 'X86':
|
||||
ffi_srcs = ('ffi.c', 'sysv.S', 'win32.S')
|
||||
elif CONFIG['FFI_TARGET'] == 'X86_64':
|
||||
|
||||
@@ -335,8 +335,6 @@ curses.h
|
||||
cxxabi.h
|
||||
DateTimeUtils.h
|
||||
dbus/dbus.h
|
||||
dbus/dbus-glib.h
|
||||
dbus/dbus-glib-lowlevel.h
|
||||
ddeml.h
|
||||
Debug.h
|
||||
dem.h
|
||||
|
||||
@@ -400,6 +400,7 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
|
||||
layers::PlanarYCbCrImage* ycbcrImage = static_cast<layers::PlanarYCbCrImage*> (aImage);
|
||||
gfxImageFormat format = SurfaceFormat::A8R8G8B8_UINT32;
|
||||
uint32_t stride = GetAlignedStride<16>(aSize.width, 4);
|
||||
auto size = stride * aSize.height;
|
||||
size_t length = BufferSizeFromStrideAndHeight(stride, aSize.height);
|
||||
if (length == 0) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@@ -413,10 +414,10 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
|
||||
stride);
|
||||
|
||||
rv = aEncoder->InitFromData(data.Elements(),
|
||||
aSize.width * aSize.height * 4,
|
||||
size,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
aSize.width * 4,
|
||||
stride,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
aOptions);
|
||||
} else {
|
||||
@@ -433,10 +434,10 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
rv = aEncoder->InitFromData(map.mData,
|
||||
aSize.width * aSize.height * 4,
|
||||
map.mStride * aSize.height,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
aSize.width * 4,
|
||||
map.mStride,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
aOptions);
|
||||
dataSurface->Unmap();
|
||||
@@ -467,10 +468,10 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
rv = aEncoder->InitFromData(map.mData,
|
||||
aSize.width * aSize.height * 4,
|
||||
map.mStride * aSize.height,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
aSize.width * 4,
|
||||
map.mStride,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
aOptions);
|
||||
emptyCanvas->Unmap();
|
||||
|
||||
@@ -77,6 +77,4 @@ if CONFIG['MOZ_GAMEPAD']:
|
||||
]
|
||||
|
||||
CFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "DXVA2Manager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "Layers.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "MediaInfo.h"
|
||||
@@ -741,6 +742,10 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
stride = mVideoStride;
|
||||
}
|
||||
if (stride <= 0) {
|
||||
LOG("CreateBasicVideoFrame: invalid stride %ld", stride);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// YV12, planar format: [YYYY....][VVVV....][UUUU....]
|
||||
// i.e., Y, then V, then U.
|
||||
@@ -763,9 +768,16 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
|
||||
if (videoHeight % 16 != 0) {
|
||||
padding = 16 - (videoHeight % 16);
|
||||
}
|
||||
uint32_t y_size = stride * (videoHeight + padding);
|
||||
uint32_t v_size = stride * (videoHeight + padding) / 4;
|
||||
uint32_t halfStride = (stride + 1) / 2;
|
||||
mozilla::CheckedInt<uint32_t> y_size_checked =
|
||||
mozilla::CheckedInt<uint32_t>(static_cast<uint32_t>(stride)) *
|
||||
(videoHeight + padding);
|
||||
if (!y_size_checked.isValid()) {
|
||||
LOG("CreateBasicVideoFrame: plane size too large");
|
||||
return E_FAIL;
|
||||
}
|
||||
uint32_t y_size = y_size_checked.value();
|
||||
uint32_t v_size = y_size / 4;
|
||||
uint32_t halfStride = static_cast<uint32_t>((static_cast<int64_t>(stride) + 1) / 2);
|
||||
uint32_t halfHeight = (videoHeight + 1) / 2;
|
||||
uint32_t halfWidth = (videoWidth + 1) / 2;
|
||||
|
||||
|
||||
@@ -818,13 +818,13 @@ generate_composite_function \
|
||||
.macro over_white_8888_8888_ca_1pixel_tail
|
||||
mvn TMP0, WK1
|
||||
teq WK1, WK1, asr #32
|
||||
bne 01f
|
||||
bcc 03f
|
||||
bne 1f
|
||||
bcc 3f
|
||||
mov WK3, WK1
|
||||
b 02f
|
||||
01: over_white_8888_8888_ca_combine WK1, WK3
|
||||
02: pixst , 4, 3, DST
|
||||
03:
|
||||
b 2f
|
||||
1: over_white_8888_8888_ca_combine WK1, WK3
|
||||
2: pixst , 4, 3, DST
|
||||
3:
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_2pixels_head
|
||||
@@ -835,21 +835,21 @@ generate_composite_function \
|
||||
pixld , 8, 3, DST
|
||||
mvn TMP0, WK1
|
||||
teq WK1, WK1, asr #32
|
||||
bne 01f
|
||||
bne 1f
|
||||
movcs WK3, WK1
|
||||
bcs 02f
|
||||
bcs 2f
|
||||
teq WK2, #0
|
||||
beq 05f
|
||||
b 02f
|
||||
01: over_white_8888_8888_ca_combine WK1, WK3
|
||||
02: mvn TMP0, WK2
|
||||
beq 5f
|
||||
b 2f
|
||||
1: over_white_8888_8888_ca_combine WK1, WK3
|
||||
2: mvn TMP0, WK2
|
||||
teq WK2, WK2, asr #32
|
||||
bne 03f
|
||||
bne 3f
|
||||
movcs WK4, WK2
|
||||
b 04f
|
||||
03: over_white_8888_8888_ca_combine WK2, WK4
|
||||
04: pixst , 8, 3, DST
|
||||
05:
|
||||
b 4f
|
||||
3: over_white_8888_8888_ca_combine WK2, WK4
|
||||
4: pixst , 8, 3, DST
|
||||
5:
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
@@ -1065,9 +1065,9 @@ generate_composite_function \
|
||||
.if offset != 0
|
||||
ldrb ORIG_W, [SRC, #offset]
|
||||
.endif
|
||||
beq 01f
|
||||
beq 1f
|
||||
teq STRIDE_M, #0xFF
|
||||
beq 02f
|
||||
beq 2f
|
||||
.endif
|
||||
uxtb16 SCRATCH, d /* rb_dest */
|
||||
uxtb16 d, d, ror #8 /* ag_dest */
|
||||
@@ -1077,13 +1077,13 @@ generate_composite_function \
|
||||
uxtab16 d, d, d, ror #8
|
||||
mov SCRATCH, SCRATCH, ror #8
|
||||
sel d, SCRATCH, d
|
||||
b 02f
|
||||
b 2f
|
||||
.if offset == 0
|
||||
48: /* Last mov d,#0 of the set - used as part of shortcut for
|
||||
* source values all 0 */
|
||||
.endif
|
||||
01: mov d, #0
|
||||
02:
|
||||
1: mov d, #0
|
||||
2:
|
||||
.endm
|
||||
|
||||
.macro in_reverse_8888_8888_tail numbytes, reg1, reg2, reg3, reg4
|
||||
|
||||
@@ -99,6 +99,4 @@ if CONFIG['MOZ_GAMEPAD']:
|
||||
]
|
||||
|
||||
CFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
||||
@@ -27,6 +27,4 @@ FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['MOZ_ENABLE_DBUS']:
|
||||
CFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
||||
+5
-2
@@ -6,7 +6,7 @@
|
||||
@depends(target)
|
||||
def force_system_ffi(target):
|
||||
# Pre-emptively move to system ffi for non-tier one platforms.
|
||||
if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'):
|
||||
if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64', 'loongarch64'):
|
||||
return True
|
||||
|
||||
imply_option('--with-system-ffi', force_system_ffi, "target")
|
||||
@@ -27,7 +27,7 @@ add_old_configure_assignment('MOZ_SYSTEM_FFI', depends_if(system_ffi)(lambda _:
|
||||
# Target selection, based on ffi/configure.ac.
|
||||
@depends_when(target, when=building_ffi)
|
||||
def ffi_target(target):
|
||||
if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'):
|
||||
if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64', 'loongarch64'):
|
||||
die('Building libffi from the tree is not supported on this platform. '
|
||||
'Use --with-system-ffi instead.')
|
||||
|
||||
@@ -50,6 +50,9 @@ def ffi_target(target):
|
||||
elif target.cpu == 'aarch64':
|
||||
target_dir = 'aarch64'
|
||||
target_name = 'AARCH64'
|
||||
elif target.cpu == 'loongarch64':
|
||||
target_dir = 'loongarch64'
|
||||
target_name = 'LOONGARCH64'
|
||||
else:
|
||||
target_dir = 'x86'
|
||||
target_name = target.cpu.upper()
|
||||
|
||||
@@ -0,0 +1,600 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2022 Xu Chenghua <xuchenghua@loongson.cn>
|
||||
2022 Cheng Lulu <chenglulu@loongson.cn>
|
||||
Based on RISC-V port
|
||||
|
||||
LoongArch Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__loongarch_soft_float)
|
||||
# define ABI_FRLEN 0
|
||||
#elif defined(__loongarch_single_float)
|
||||
# define ABI_FRLEN 32
|
||||
# define ABI_FLOAT float
|
||||
#elif defined(__loongarch_double_float)
|
||||
# define ABI_FRLEN 64
|
||||
# define ABI_FLOAT double
|
||||
#else
|
||||
#error unsupported LoongArch floating-point ABI
|
||||
#endif
|
||||
|
||||
#define NARGREG 8
|
||||
#define STKALIGN 16
|
||||
#define MAXCOPYARG (2 * sizeof (double))
|
||||
|
||||
/* call_context registers
|
||||
- 8 floating point parameter/result registers.
|
||||
- 8 integer parameter/result registers.
|
||||
- 2 registers used by the assembly code to in-place construct its own
|
||||
stack frame
|
||||
- frame register
|
||||
- return register
|
||||
*/
|
||||
typedef struct call_context
|
||||
{
|
||||
ABI_FLOAT fa[8];
|
||||
size_t a[10];
|
||||
} call_context;
|
||||
|
||||
typedef struct call_builder
|
||||
{
|
||||
call_context *aregs;
|
||||
int used_integer;
|
||||
int used_float;
|
||||
size_t *used_stack;
|
||||
size_t *stack;
|
||||
size_t next_struct_area;
|
||||
} call_builder;
|
||||
|
||||
/* Integer (not pointer) less than ABI GRLEN. */
|
||||
/* FFI_TYPE_INT does not appear to be used. */
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
# define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT64)
|
||||
#else
|
||||
# define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT32)
|
||||
#endif
|
||||
|
||||
#if ABI_FRLEN
|
||||
typedef struct float_struct_info
|
||||
{
|
||||
char as_elements;
|
||||
char type1;
|
||||
char offset2;
|
||||
char type2;
|
||||
} float_struct_info;
|
||||
|
||||
#if ABI_FRLEN >= 64
|
||||
# define IS_FLOAT(type) ((type) >= FFI_TYPE_FLOAT && (type) <= FFI_TYPE_DOUBLE)
|
||||
#else
|
||||
# define IS_FLOAT(type) ((type) == FFI_TYPE_FLOAT)
|
||||
#endif
|
||||
|
||||
static ffi_type **
|
||||
flatten_struct (ffi_type *in, ffi_type **out, ffi_type **out_end)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (out == out_end)
|
||||
return out;
|
||||
if (in->type != FFI_TYPE_STRUCT)
|
||||
*(out++) = in;
|
||||
else
|
||||
for (i = 0; in->elements[i]; i++)
|
||||
out = flatten_struct (in->elements[i], out, out_end);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Structs with at most two fields after flattening, one of which is of
|
||||
floating point type, are passed in multiple registers if sufficient
|
||||
registers are available. */
|
||||
static float_struct_info
|
||||
struct_passed_as_elements (call_builder *cb, ffi_type *top)
|
||||
{
|
||||
float_struct_info ret = {0, 0, 0, 0};
|
||||
ffi_type *fields[3];
|
||||
int num_floats, num_ints;
|
||||
int num_fields = flatten_struct (top, fields, fields + 3) - fields;
|
||||
|
||||
if (num_fields == 1)
|
||||
{
|
||||
if (IS_FLOAT (fields[0]->type))
|
||||
{
|
||||
ret.as_elements = 1;
|
||||
ret.type1 = fields[0]->type;
|
||||
}
|
||||
}
|
||||
else if (num_fields == 2)
|
||||
{
|
||||
num_floats = IS_FLOAT (fields[0]->type) + IS_FLOAT (fields[1]->type);
|
||||
num_ints = IS_INT (fields[0]->type) + IS_INT (fields[1]->type);
|
||||
if (num_floats == 0 || num_floats + num_ints != 2)
|
||||
return ret;
|
||||
if (cb->used_float + num_floats > NARGREG
|
||||
|| cb->used_integer + (2 - num_floats) > NARGREG)
|
||||
return ret;
|
||||
if (!IS_FLOAT (fields[0]->type) && !IS_FLOAT (fields[1]->type))
|
||||
return ret;
|
||||
|
||||
ret.type1 = fields[0]->type;
|
||||
ret.type2 = fields[1]->type;
|
||||
ret.offset2 = ALIGN (fields[0]->size, fields[1]->alignment);
|
||||
ret.as_elements = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocates a single register, float register, or GRLEN-sized stack slot to a
|
||||
datum. */
|
||||
static void
|
||||
marshal_atom (call_builder *cb, int type, void *data)
|
||||
{
|
||||
size_t value = 0;
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
value = *(uint8_t *) data;
|
||||
break;
|
||||
case FFI_TYPE_SINT8:
|
||||
value = *(int8_t *) data;
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
value = *(uint16_t *) data;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
value = *(int16_t *) data;
|
||||
break;
|
||||
/* 32-bit quantities are always sign-extended in the ABI. */
|
||||
case FFI_TYPE_UINT32:
|
||||
value = *(int32_t *) data;
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
value = *(int32_t *) data;
|
||||
break;
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
value = *(uint64_t *) data;
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
value = *(int64_t *) data;
|
||||
break;
|
||||
#endif
|
||||
case FFI_TYPE_POINTER:
|
||||
value = *(size_t *) data;
|
||||
break;
|
||||
|
||||
#if ABI_FRLEN >= 32
|
||||
case FFI_TYPE_FLOAT:
|
||||
*(float *)(cb->aregs->fa + cb->used_float++) = *(float *) data;
|
||||
return;
|
||||
#endif
|
||||
#if ABI_FRLEN >= 64
|
||||
case FFI_TYPE_DOUBLE:
|
||||
(cb->aregs->fa[cb->used_float++]) = *(double *) data;
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cb->used_integer == NARGREG)
|
||||
*cb->used_stack++ = value;
|
||||
else
|
||||
cb->aregs->a[cb->used_integer++] = value;
|
||||
}
|
||||
|
||||
static void
|
||||
unmarshal_atom (call_builder *cb, int type, void *data)
|
||||
{
|
||||
size_t value;
|
||||
switch (type)
|
||||
{
|
||||
#if ABI_FRLEN >= 32
|
||||
case FFI_TYPE_FLOAT:
|
||||
*(float *) data = *(float *)(cb->aregs->fa + cb->used_float++);
|
||||
return;
|
||||
#endif
|
||||
#if ABI_FRLEN >= 64
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*(double *) data = cb->aregs->fa[cb->used_float++];
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cb->used_integer == NARGREG)
|
||||
value = *cb->used_stack++;
|
||||
else
|
||||
value = cb->aregs->a[cb->used_integer++];
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
#endif
|
||||
case FFI_TYPE_POINTER:
|
||||
*(ffi_arg *)data = value;
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate and copy a structure that is passed by value on the stack and
|
||||
return a pointer to it. */
|
||||
static void *
|
||||
allocate_and_copy_struct_to_stack (call_builder *cb, void *data,
|
||||
ffi_type *type)
|
||||
{
|
||||
size_t dest = cb->next_struct_area - type->size;
|
||||
|
||||
dest = ALIGN_DOWN (dest, type->alignment);
|
||||
cb->next_struct_area = dest;
|
||||
|
||||
return memcpy ((char *)cb->stack + dest, data, type->size);
|
||||
}
|
||||
|
||||
/* Adds an argument to a call, or a not by reference return value. */
|
||||
static void
|
||||
marshal (call_builder *cb, ffi_type *type, int var, void *data)
|
||||
{
|
||||
size_t realign[2];
|
||||
|
||||
#if ABI_FRLEN
|
||||
if (!var && type->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
float_struct_info fsi = struct_passed_as_elements (cb, type);
|
||||
if (fsi.as_elements)
|
||||
{
|
||||
marshal_atom (cb, fsi.type1, data);
|
||||
if (fsi.offset2)
|
||||
marshal_atom (cb, fsi.type2, ((char *) data) + fsi.offset2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!var && cb->used_float < NARGREG
|
||||
&& IS_FLOAT (type->type))
|
||||
{
|
||||
marshal_atom (cb, type->type, data);
|
||||
return;
|
||||
}
|
||||
|
||||
double promoted;
|
||||
if (var && type->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
/* C standard requires promoting float -> double for variable arg. */
|
||||
promoted = *(float *) data;
|
||||
type = &ffi_type_double;
|
||||
data = &promoted;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (type->size > 2 * __SIZEOF_POINTER__)
|
||||
/* Pass by reference. */
|
||||
{
|
||||
allocate_and_copy_struct_to_stack (cb, data, type);
|
||||
data = (char *)cb->stack + cb->next_struct_area;
|
||||
marshal_atom (cb, FFI_TYPE_POINTER, &data);
|
||||
}
|
||||
else if (IS_INT (type->type) || type->type == FFI_TYPE_POINTER)
|
||||
marshal_atom (cb, type->type, data);
|
||||
else
|
||||
{
|
||||
/* Overlong integers, soft-float floats, and structs without special
|
||||
float handling are treated identically from this point on. */
|
||||
|
||||
/* Variadics are aligned even in registers. */
|
||||
if (type->alignment > __SIZEOF_POINTER__)
|
||||
{
|
||||
if (var)
|
||||
cb->used_integer = ALIGN (cb->used_integer, 2);
|
||||
cb->used_stack
|
||||
= (size_t *) ALIGN (cb->used_stack, 2 * __SIZEOF_POINTER__);
|
||||
}
|
||||
|
||||
memcpy (realign, data, type->size);
|
||||
if (type->size > 0)
|
||||
marshal_atom (cb, FFI_TYPE_POINTER, realign);
|
||||
if (type->size > __SIZEOF_POINTER__)
|
||||
marshal_atom (cb, FFI_TYPE_POINTER, realign + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* For arguments passed by reference returns the pointer, otherwise the arg
|
||||
is copied (up to MAXCOPYARG bytes). */
|
||||
static void *
|
||||
unmarshal (call_builder *cb, ffi_type *type, int var, void *data)
|
||||
{
|
||||
size_t realign[2];
|
||||
void *pointer;
|
||||
|
||||
#if ABI_FRLEN
|
||||
if (!var && type->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
float_struct_info fsi = struct_passed_as_elements (cb, type);
|
||||
if (fsi.as_elements)
|
||||
{
|
||||
unmarshal_atom (cb, fsi.type1, data);
|
||||
if (fsi.offset2)
|
||||
unmarshal_atom (cb, fsi.type2, ((char *) data) + fsi.offset2);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
if (!var && cb->used_float < NARGREG
|
||||
&& IS_FLOAT (type->type))
|
||||
{
|
||||
unmarshal_atom (cb, type->type, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
if (var && type->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
int m = cb->used_integer;
|
||||
void *promoted
|
||||
= m < NARGREG ? cb->aregs->a + m : cb->used_stack + m - NARGREG + 1;
|
||||
*(float *) promoted = *(double *) promoted;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (type->size > 2 * __SIZEOF_POINTER__)
|
||||
{
|
||||
/* Pass by reference. */
|
||||
unmarshal_atom (cb, FFI_TYPE_POINTER, (char *) &pointer);
|
||||
return pointer;
|
||||
}
|
||||
else if (IS_INT (type->type) || type->type == FFI_TYPE_POINTER)
|
||||
{
|
||||
unmarshal_atom (cb, type->type, data);
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Overlong integers, soft-float floats, and structs without special
|
||||
float handling are treated identically from this point on. */
|
||||
|
||||
/* Variadics are aligned even in registers. */
|
||||
if (type->alignment > __SIZEOF_POINTER__)
|
||||
{
|
||||
if (var)
|
||||
cb->used_integer = ALIGN (cb->used_integer, 2);
|
||||
cb->used_stack
|
||||
= (size_t *) ALIGN (cb->used_stack, 2 * __SIZEOF_POINTER__);
|
||||
}
|
||||
|
||||
if (type->size > 0)
|
||||
unmarshal_atom (cb, FFI_TYPE_POINTER, realign);
|
||||
if (type->size > __SIZEOF_POINTER__)
|
||||
unmarshal_atom (cb, FFI_TYPE_POINTER, realign + 1);
|
||||
memcpy (data, realign, type->size);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
passed_by_ref (call_builder *cb, ffi_type *type, int var)
|
||||
{
|
||||
#if ABI_FRLEN
|
||||
if (!var && type->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
float_struct_info fsi = struct_passed_as_elements (cb, type);
|
||||
if (fsi.as_elements)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return type->size > 2 * __SIZEOF_POINTER__;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
cif->loongarch_nfixedargs = cif->nargs;
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing when we have a variadic
|
||||
function. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep_var (ffi_cif *cif, unsigned int nfixedargs,
|
||||
unsigned int ntotalargs)
|
||||
{
|
||||
cif->loongarch_nfixedargs = nfixedargs;
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Low level routine for calling functions. */
|
||||
extern void ffi_call_asm (void *stack, struct call_context *regs,
|
||||
void (*fn) (void), void *closure) FFI_HIDDEN;
|
||||
|
||||
static void
|
||||
ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
|
||||
void *closure)
|
||||
{
|
||||
/* This is a conservative estimate, assuming a complex return value and
|
||||
that all remaining arguments are long long / __int128 */
|
||||
size_t arg_bytes = cif->bytes;
|
||||
size_t rval_bytes = 0;
|
||||
if (rvalue == NULL && cif->rtype->size > 2 * __SIZEOF_POINTER__)
|
||||
rval_bytes = ALIGN (cif->rtype->size, STKALIGN);
|
||||
size_t alloc_size = arg_bytes + rval_bytes + sizeof (call_context);
|
||||
|
||||
/* The assembly code will deallocate all stack data at lower addresses
|
||||
than the argument region, so we need to allocate the frame and the
|
||||
return value after the arguments in a single allocation. */
|
||||
/* Argument region must be 16-byte aligned in LP64 ABIs. */
|
||||
size_t alloc_base = ALIGN (alloca (alloc_size + STKALIGN - 1), STKALIGN);
|
||||
|
||||
if (rval_bytes)
|
||||
rvalue = (void *) (alloc_base + arg_bytes);
|
||||
|
||||
call_builder cb;
|
||||
cb.used_float = cb.used_integer = 0;
|
||||
cb.aregs = (call_context *) (alloc_base + arg_bytes + rval_bytes);
|
||||
cb.used_stack = (void *) alloc_base;
|
||||
cb.stack = (void *) alloc_base;
|
||||
cb.next_struct_area = arg_bytes;
|
||||
|
||||
int return_by_ref = passed_by_ref (&cb, cif->rtype, 0);
|
||||
if (return_by_ref)
|
||||
cb.aregs->a[cb.used_integer++] = (size_t)rvalue;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
marshal (&cb, cif->arg_types[i], i >= cif->loongarch_nfixedargs,
|
||||
avalue[i]);
|
||||
|
||||
ffi_call_asm ((void *) alloc_base, cb.aregs, fn, closure);
|
||||
|
||||
cb.used_float = cb.used_integer = 0;
|
||||
if (!return_by_ref && rvalue)
|
||||
unmarshal (&cb, cif->rtype, 0, rvalue);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_call_int (cif, fn, rvalue, avalue, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
|
||||
void *closure)
|
||||
{
|
||||
ffi_call_int (cif, fn, rvalue, avalue, closure);
|
||||
}
|
||||
|
||||
extern void ffi_closure_asm (void) FFI_HIDDEN;
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data, void *codeloc)
|
||||
{
|
||||
uint32_t *tramp = (uint32_t *) &closure->tramp[0];
|
||||
uint64_t fn = (uint64_t) (uintptr_t) ffi_closure_asm;
|
||||
|
||||
if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
#if defined(FFI_EXEC_STATIC_TRAMP)
|
||||
if (ffi_tramp_is_present(closure))
|
||||
{
|
||||
ffi_tramp_set_parms (closure->ftramp, ffi_closure_asm, closure);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fill the dynamic trampoline. We will call ffi_closure_inner with codeloc,
|
||||
not closure, but as long as the memory is readable it should work. */
|
||||
tramp[0] = 0x1800000c; /* pcaddi $t0, 0 (i.e. $t0 <- tramp) */
|
||||
tramp[1] = 0x28c0418d; /* ld.d $t1, $t0, 16 */
|
||||
tramp[2] = 0x4c0001a0; /* jirl $zero, $t1, 0 */
|
||||
tramp[3] = 0x03400000; /* nop */
|
||||
tramp[4] = fn;
|
||||
tramp[5] = fn >> 32;
|
||||
|
||||
__builtin___clear_cache (codeloc, codeloc + FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
#if defined(FFI_EXEC_STATIC_TRAMP)
|
||||
out:
|
||||
#endif
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Called by the assembly code with aregs pointing to saved argument registers
|
||||
and stack pointing to the stacked arguments. Return values passed in
|
||||
registers will be reloaded from aregs. */
|
||||
void FFI_HIDDEN
|
||||
ffi_closure_inner (ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data, size_t *stack, call_context *aregs)
|
||||
{
|
||||
void **avalue = alloca (cif->nargs * sizeof (void *));
|
||||
/* Storage for arguments which will be copied by unmarshal(). We could
|
||||
theoretically avoid the copies in many cases and use at most 128 bytes
|
||||
of memory, but allocating disjoint storage for each argument is
|
||||
simpler. */
|
||||
char *astorage = alloca (cif->nargs * MAXCOPYARG);
|
||||
void *rvalue;
|
||||
call_builder cb;
|
||||
int return_by_ref;
|
||||
int i;
|
||||
|
||||
cb.aregs = aregs;
|
||||
cb.used_integer = cb.used_float = 0;
|
||||
cb.used_stack = stack;
|
||||
|
||||
return_by_ref = passed_by_ref (&cb, cif->rtype, 0);
|
||||
if (return_by_ref)
|
||||
unmarshal (&cb, &ffi_type_pointer, 0, &rvalue);
|
||||
else
|
||||
rvalue = alloca (cif->rtype->size);
|
||||
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
avalue[i]
|
||||
= unmarshal (&cb, cif->arg_types[i], i >= cif->loongarch_nfixedargs,
|
||||
astorage + i * MAXCOPYARG);
|
||||
|
||||
fun (cif, rvalue, avalue, user_data);
|
||||
|
||||
if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID)
|
||||
{
|
||||
cb.used_integer = cb.used_float = 0;
|
||||
marshal (&cb, cif->rtype, 0, rvalue);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FFI_EXEC_STATIC_TRAMP)
|
||||
void *
|
||||
ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
|
||||
{
|
||||
extern void *trampoline_code_table;
|
||||
|
||||
*tramp_size = 16;
|
||||
/* A mapping size of 64K is chosen to cover the page sizes of 4K, 16K, and
|
||||
64K. */
|
||||
*map_size = 1 << 16;
|
||||
return &trampoline_code_table;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2022 Xu Chenghua <xuchenghua@loongson.cn>
|
||||
2022 Cheng Lulu <chenglulu@loongson.cn>
|
||||
|
||||
Target configuration macros for LoongArch.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_H
|
||||
#error \
|
||||
"Please do not include ffitarget.h directly into your source. Use ffi.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef __loongarch__
|
||||
#error \
|
||||
"libffi was configured for a LoongArch target but this does not appear to be a LoongArch compiler."
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi
|
||||
{
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_LP64S,
|
||||
FFI_LP64F,
|
||||
FFI_LP64D,
|
||||
FFI_LAST_ABI,
|
||||
|
||||
#if defined(__loongarch64)
|
||||
#if defined(__loongarch_soft_float)
|
||||
FFI_DEFAULT_ABI = FFI_LP64S
|
||||
#elif defined(__loongarch_single_float)
|
||||
FFI_DEFAULT_ABI = FFI_LP64F
|
||||
#elif defined(__loongarch_double_float)
|
||||
FFI_DEFAULT_ABI = FFI_LP64D
|
||||
#else
|
||||
#error unsupported LoongArch floating-point ABI
|
||||
#endif
|
||||
#else
|
||||
#error unsupported LoongArch base architecture
|
||||
#endif
|
||||
} ffi_abi;
|
||||
|
||||
#endif /* LIBFFI_ASM */
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#define FFI_EXTRA_CIF_FIELDS \
|
||||
unsigned loongarch_nfixedargs; \
|
||||
unsigned loongarch_unused;
|
||||
#define FFI_TARGET_SPECIFIC_VARIADIC
|
||||
#endif
|
||||
@@ -0,0 +1,327 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2022 Xu Chenghua <xuchenghua@loongson.cn>
|
||||
2022 Cheng Lulu <chenglulu@loongson.cn>
|
||||
|
||||
LoongArch Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Define aliases so that we can handle all ABIs uniformly. */
|
||||
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
# define PTRS 8
|
||||
# define LARG ld.d
|
||||
# define SARG st.d
|
||||
#else
|
||||
# define PTRS 4
|
||||
# define LARG ld.w
|
||||
# define SARG st.w
|
||||
#endif
|
||||
|
||||
#if defined(__loongarch_single_float)
|
||||
# define FLTS 4
|
||||
# define FLD fld.w
|
||||
# define FST fst.w
|
||||
#elif defined(__loongarch_double_float)
|
||||
# define FLTS 8
|
||||
# define FLARG fld.d
|
||||
# define FSARG fst.d
|
||||
#elif defined(__loongarch_soft_float)
|
||||
# define FLTS 0
|
||||
#else
|
||||
#error unsupported LoongArch floating-point ABI
|
||||
#endif
|
||||
|
||||
.text
|
||||
.globl ffi_call_asm
|
||||
.type ffi_call_asm, @function
|
||||
.hidden ffi_call_asm
|
||||
/* struct call_context
|
||||
{
|
||||
ABI_FLOAT fa[8];
|
||||
size_t a[10];
|
||||
}
|
||||
|
||||
- 8 floating point parameter/result registers (fa[0] - fa[7])
|
||||
- 8 integer parameter/result registers (a[0] - a[7])
|
||||
- 2 registers used by the assembly code to in-place construct its own stack
|
||||
frame.
|
||||
- frame pointer (a[8])
|
||||
- return address (a[9])
|
||||
|
||||
void ffi_call_asm (size_t *stackargs, struct call_context *regargs,
|
||||
void (*fn)(void), void *closure); */
|
||||
|
||||
#define FRAME_LEN (8 * FLTS + 10 * PTRS)
|
||||
|
||||
ffi_call_asm:
|
||||
.cfi_startproc
|
||||
|
||||
/* We are NOT going to set up an ordinary stack frame. In order to pass
|
||||
the stacked args to the called function, we adjust our stack pointer
|
||||
to a0, which is in the _caller's_ alloca area. We establish our own
|
||||
stack frame at the end of the call_context.
|
||||
|
||||
Anything below the arguments will be freed at this point, although
|
||||
we preserve the call_context so that it can be read back in the
|
||||
caller. */
|
||||
|
||||
.cfi_def_cfa 5, FRAME_LEN # Interim CFA based on a1.
|
||||
SARG $fp, $a1, FRAME_LEN - 2*PTRS
|
||||
.cfi_offset 22, -2*PTRS
|
||||
SARG $ra, $a1, FRAME_LEN - 1*PTRS
|
||||
.cfi_offset 1, -1*PTRS
|
||||
|
||||
addi.d $fp, $a1, FRAME_LEN
|
||||
move $sp, $a0
|
||||
.cfi_def_cfa 22, 0 # Our frame is fully set up.
|
||||
|
||||
# Load arguments.
|
||||
move $t1, $a2
|
||||
move $t2, $a3
|
||||
|
||||
#if FLTS
|
||||
FLARG $fa0, $fp, -FRAME_LEN+0*FLTS
|
||||
FLARG $fa1, $fp, -FRAME_LEN+1*FLTS
|
||||
FLARG $fa2, $fp, -FRAME_LEN+2*FLTS
|
||||
FLARG $fa3, $fp, -FRAME_LEN+3*FLTS
|
||||
FLARG $fa4, $fp, -FRAME_LEN+4*FLTS
|
||||
FLARG $fa5, $fp, -FRAME_LEN+5*FLTS
|
||||
FLARG $fa6, $fp, -FRAME_LEN+6*FLTS
|
||||
FLARG $fa7, $fp, -FRAME_LEN+7*FLTS
|
||||
#endif
|
||||
|
||||
LARG $a0, $fp, -FRAME_LEN+8*FLTS+0*PTRS
|
||||
LARG $a1, $fp, -FRAME_LEN+8*FLTS+1*PTRS
|
||||
LARG $a2, $fp, -FRAME_LEN+8*FLTS+2*PTRS
|
||||
LARG $a3, $fp, -FRAME_LEN+8*FLTS+3*PTRS
|
||||
LARG $a4, $fp, -FRAME_LEN+8*FLTS+4*PTRS
|
||||
LARG $a5, $fp, -FRAME_LEN+8*FLTS+5*PTRS
|
||||
LARG $a6, $fp, -FRAME_LEN+8*FLTS+6*PTRS
|
||||
LARG $a7, $fp, -FRAME_LEN+8*FLTS+7*PTRS
|
||||
|
||||
/* Call */
|
||||
jirl $ra, $t1, 0
|
||||
|
||||
#if FLTS
|
||||
/* Save return values - only a0/a1 (fa0/fa1) are used. */
|
||||
FSARG $fa0, $fp, -FRAME_LEN+0*FLTS
|
||||
FSARG $fa1, $fp, -FRAME_LEN+1*FLTS
|
||||
#endif
|
||||
|
||||
SARG $a0, $fp, -FRAME_LEN+8*FLTS+0*PTRS
|
||||
SARG $a1, $fp, -FRAME_LEN+8*FLTS+1*PTRS
|
||||
|
||||
/* Restore and return. */
|
||||
addi.d $sp, $fp, -FRAME_LEN
|
||||
.cfi_def_cfa 3, FRAME_LEN
|
||||
LARG $ra, $fp, -1*PTRS
|
||||
.cfi_restore 1
|
||||
LARG $fp, $fp, -2*PTRS
|
||||
.cfi_restore 22
|
||||
jr $ra
|
||||
.cfi_endproc
|
||||
.size ffi_call_asm, .-ffi_call_asm
|
||||
|
||||
|
||||
/* ffi_closure_asm. Expects address of the passed-in ffi_closure in t0.
|
||||
void ffi_closure_inner (ffi_cif *cif,
|
||||
void (*fun)(ffi_cif *, void *, void **, void *),
|
||||
void *user_data,
|
||||
size_t *stackargs, struct call_context *regargs) */
|
||||
|
||||
.globl ffi_closure_asm
|
||||
.hidden ffi_closure_asm
|
||||
.type ffi_closure_asm, @function
|
||||
|
||||
ffi_closure_asm:
|
||||
.cfi_startproc
|
||||
addi.d $sp, $sp, -FRAME_LEN
|
||||
.cfi_def_cfa_offset FRAME_LEN
|
||||
|
||||
/* Make a frame. */
|
||||
SARG $fp, $sp, FRAME_LEN - 2*PTRS
|
||||
.cfi_offset 22, -2*PTRS
|
||||
SARG $ra, $sp, FRAME_LEN - 1*PTRS
|
||||
.cfi_offset 1, -1*PTRS
|
||||
addi.d $fp, $sp, FRAME_LEN
|
||||
|
||||
/* Save arguments. */
|
||||
#if FLTS
|
||||
FSARG $fa0, $sp, 0*FLTS
|
||||
FSARG $fa1, $sp, 1*FLTS
|
||||
FSARG $fa2, $sp, 2*FLTS
|
||||
FSARG $fa3, $sp, 3*FLTS
|
||||
FSARG $fa4, $sp, 4*FLTS
|
||||
FSARG $fa5, $sp, 5*FLTS
|
||||
FSARG $fa6, $sp, 6*FLTS
|
||||
FSARG $fa7, $sp, 7*FLTS
|
||||
#endif
|
||||
|
||||
SARG $a0, $sp, 8*FLTS+0*PTRS
|
||||
SARG $a1, $sp, 8*FLTS+1*PTRS
|
||||
SARG $a2, $sp, 8*FLTS+2*PTRS
|
||||
SARG $a3, $sp, 8*FLTS+3*PTRS
|
||||
SARG $a4, $sp, 8*FLTS+4*PTRS
|
||||
SARG $a5, $sp, 8*FLTS+5*PTRS
|
||||
SARG $a6, $sp, 8*FLTS+6*PTRS
|
||||
SARG $a7, $sp, 8*FLTS+7*PTRS
|
||||
|
||||
/* Enter C */
|
||||
LARG $a0, $t0, FFI_TRAMPOLINE_SIZE+0*PTRS
|
||||
LARG $a1, $t0, FFI_TRAMPOLINE_SIZE+1*PTRS
|
||||
LARG $a2, $t0, FFI_TRAMPOLINE_SIZE+2*PTRS
|
||||
addi.d $a3, $sp, FRAME_LEN
|
||||
move $a4, $sp
|
||||
|
||||
bl ffi_closure_inner
|
||||
|
||||
/* Return values. */
|
||||
#if FLTS
|
||||
FLARG $fa0, $sp, 0*FLTS
|
||||
FLARG $fa1, $sp, 1*FLTS
|
||||
#endif
|
||||
|
||||
LARG $a0, $sp, 8*FLTS+0*PTRS
|
||||
LARG $a1, $sp, 8*FLTS+1*PTRS
|
||||
|
||||
/* Restore and return. */
|
||||
LARG $ra, $sp, FRAME_LEN-1*PTRS
|
||||
.cfi_restore 1
|
||||
LARG $fp, $sp, FRAME_LEN-2*PTRS
|
||||
.cfi_restore 22
|
||||
addi.d $sp, $sp, FRAME_LEN
|
||||
.cfi_def_cfa_offset 0
|
||||
jr $ra
|
||||
.cfi_endproc
|
||||
.size ffi_closure_asm, .-ffi_closure_asm
|
||||
|
||||
/* Static trampoline code table, in which each element is a trampoline.
|
||||
|
||||
The trampoline clobbers t0 and t1, but we don't save them on the stack
|
||||
because our psABI explicitly says they are scratch registers, at least for
|
||||
ELF. Our dynamic trampoline is already clobbering them anyway.
|
||||
|
||||
The trampoline has two parameters - target code to jump to and data for
|
||||
the target code. The trampoline extracts the parameters from its parameter
|
||||
block (see tramp_table_map()). The trampoline saves the data address in
|
||||
t0 and jumps to the target code. As ffi_closure_asm() already expects the
|
||||
data address to be in t0, we don't need a "ffi_closure_asm_alt". */
|
||||
|
||||
#if defined(FFI_EXEC_STATIC_TRAMP)
|
||||
.align 16
|
||||
.globl trampoline_code_table
|
||||
.hidden trampoline_code_table
|
||||
.type trampoline_code_table, @function
|
||||
|
||||
trampoline_code_table:
|
||||
|
||||
.rept 65536 / 16
|
||||
pcaddu12i $t1, 16 # 65536 >> 12
|
||||
ld.d $t0, $t1, 0
|
||||
ld.d $t1, $t1, 8
|
||||
jirl $zero, $t1, 0
|
||||
.endr
|
||||
.size trampoline_code_table, .-trampoline_code_table
|
||||
|
||||
.align 2
|
||||
#endif
|
||||
|
||||
/* ffi_go_closure_asm. Expects address of the passed-in ffi_go_closure in t2.
|
||||
void ffi_closure_inner (ffi_cif *cif,
|
||||
void (*fun)(ffi_cif *, void *, void **, void *),
|
||||
void *user_data,
|
||||
size_t *stackargs, struct call_context *regargs) */
|
||||
|
||||
.globl ffi_go_closure_asm
|
||||
.hidden ffi_go_closure_asm
|
||||
.type ffi_go_closure_asm, @function
|
||||
|
||||
ffi_go_closure_asm:
|
||||
.cfi_startproc
|
||||
addi.d $sp, $sp, -FRAME_LEN
|
||||
.cfi_def_cfa_offset FRAME_LEN
|
||||
|
||||
/* Make a frame. */
|
||||
SARG $fp, $sp, FRAME_LEN - 2*PTRS
|
||||
.cfi_offset 22, -2*PTRS
|
||||
SARG $ra, $sp, FRAME_LEN - 1*PTRS
|
||||
.cfi_offset 1, -1*PTRS
|
||||
addi.d $fp, $sp, FRAME_LEN
|
||||
|
||||
/* Save arguments. */
|
||||
#if FLTS
|
||||
FSARG $fa0, $sp, 0*FLTS
|
||||
FSARG $fa1, $sp, 1*FLTS
|
||||
FSARG $fa2, $sp, 2*FLTS
|
||||
FSARG $fa3, $sp, 3*FLTS
|
||||
FSARG $fa4, $sp, 4*FLTS
|
||||
FSARG $fa5, $sp, 5*FLTS
|
||||
FSARG $fa6, $sp, 6*FLTS
|
||||
FSARG $fa7, $sp, 7*FLTS
|
||||
#endif
|
||||
|
||||
SARG $a0, $sp, 8*FLTS+0*PTRS
|
||||
SARG $a1, $sp, 8*FLTS+1*PTRS
|
||||
SARG $a2, $sp, 8*FLTS+2*PTRS
|
||||
SARG $a3, $sp, 8*FLTS+3*PTRS
|
||||
SARG $a4, $sp, 8*FLTS+4*PTRS
|
||||
SARG $a5, $sp, 8*FLTS+5*PTRS
|
||||
SARG $a6, $sp, 8*FLTS+6*PTRS
|
||||
SARG $a7, $sp, 8*FLTS+7*PTRS
|
||||
|
||||
/* Enter C */
|
||||
LARG $a0, $t2, 1*PTRS
|
||||
LARG $a1, $t2, 2*PTRS
|
||||
move $a2, $t2
|
||||
addi.d $a3, $sp, FRAME_LEN
|
||||
move $a4, $sp
|
||||
|
||||
bl ffi_closure_inner
|
||||
|
||||
/* Return values. */
|
||||
#if FLTS
|
||||
FLARG $fa0, $sp, 0*FLTS
|
||||
FLARG $fa1, $sp, 1*FLTS
|
||||
#endif
|
||||
|
||||
LARG $a0, $sp, 8*FLTS+0*PTRS
|
||||
LARG $a1, $sp, 8*FLTS+1*PTRS
|
||||
|
||||
/* Restore and return. */
|
||||
LARG $ra, $sp, FRAME_LEN-1*PTRS
|
||||
.cfi_restore 1
|
||||
LARG $fp, $sp, FRAME_LEN-2*PTRS
|
||||
.cfi_restore 22
|
||||
addi.d $sp, $sp, FRAME_LEN
|
||||
.cfi_def_cfa_offset 0
|
||||
jr $ra
|
||||
.cfi_endproc
|
||||
.size ffi_go_closure_asm, .-ffi_go_closure_asm
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
+70
-43
@@ -860,19 +860,30 @@ GlobalHelperThreadState::waitForAllThreads()
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
GlobalHelperThreadState::checkTaskThreadLimit(size_t maxThreads) const
|
||||
GlobalHelperThreadState::checkTaskThreadLimit(size_t maxThreads, bool isMaster) const
|
||||
{
|
||||
if (maxThreads >= threadCount)
|
||||
return true;
|
||||
|
||||
size_t count = 0;
|
||||
size_t idle = 0;
|
||||
for (auto& thread : *threads) {
|
||||
if (thread.currentTask.isSome() && thread.currentTask->is<T>())
|
||||
count++;
|
||||
if (thread.currentTask.isSome()) {
|
||||
if (thread.currentTask->is<T>())
|
||||
count++;
|
||||
} else {
|
||||
idle++;
|
||||
}
|
||||
if (count >= maxThreads)
|
||||
return false;
|
||||
}
|
||||
|
||||
// At least the current thread is idle.
|
||||
MOZ_ASSERT(idle > 0);
|
||||
|
||||
if (isMaster && idle <= 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -916,11 +927,7 @@ GlobalHelperThreadState::maxParseThreads() const
|
||||
if (IsHelperThreadSimulatingOOM(js::oom::THREAD_TYPE_PARSE))
|
||||
return 1;
|
||||
|
||||
// Don't allow simultaneous off thread parses, to reduce contention on the
|
||||
// atoms table. Note that wasm compilation depends on this to avoid
|
||||
// stalling the helper thread, as off thread parse tasks can trigger and
|
||||
// block on other off thread wasm compilation tasks.
|
||||
return 1;
|
||||
return threadCount;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -1091,7 +1098,8 @@ GlobalHelperThreadState::pendingIonCompileHasSufficientPriority(
|
||||
bool
|
||||
GlobalHelperThreadState::canStartParseTask(const AutoLockHelperThreadState& lock)
|
||||
{
|
||||
return !parseWorklist(lock).empty() && checkTaskThreadLimit<ParseTask*>(maxParseThreads());
|
||||
return !parseWorklist(lock).empty() &&
|
||||
checkTaskThreadLimit<ParseTask*>(maxParseThreads(), /* isMaster = */ true);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1892,49 +1900,68 @@ HelperThread::threadLoop()
|
||||
while (true) {
|
||||
MOZ_ASSERT(idle());
|
||||
|
||||
// Block until a task is available. Save the value of whether we are
|
||||
// going to do an Ion compile, in case the value returned by the method
|
||||
// changes.
|
||||
bool ionCompile = false;
|
||||
js::oom::ThreadType task;
|
||||
while (true) {
|
||||
if (terminate)
|
||||
return;
|
||||
if ((ionCompile = HelperThreadState().pendingIonCompileHasSufficientPriority(lock)) ||
|
||||
HelperThreadState().canStartWasmCompile(lock) ||
|
||||
HelperThreadState().canStartPromiseTask(lock) ||
|
||||
HelperThreadState().canStartParseTask(lock) ||
|
||||
HelperThreadState().canStartCompressionTask(lock) ||
|
||||
HelperThreadState().canStartGCHelperTask(lock) ||
|
||||
HelperThreadState().canStartGCParallelTask(lock))
|
||||
{
|
||||
|
||||
// Select the task type to run. Task priority is determined
|
||||
// exclusively here.
|
||||
//
|
||||
// The selectors may depend on the HelperThreadState not changing
|
||||
// between task selection and task execution, in particular, on new
|
||||
// tasks not being added (because of the lifo structure of the work
|
||||
// lists). Unlocking the HelperThreadState between task selection
|
||||
// and execution is not well-defined.
|
||||
if (HelperThreadState().canStartGCParallelTask(lock))
|
||||
task = js::oom::THREAD_TYPE_GCPARALLEL;
|
||||
else if (HelperThreadState().canStartGCHelperTask(lock))
|
||||
task = js::oom::THREAD_TYPE_GCHELPER;
|
||||
else if (HelperThreadState().pendingIonCompileHasSufficientPriority(lock))
|
||||
task = js::oom::THREAD_TYPE_ION;
|
||||
else if (HelperThreadState().canStartWasmCompile(lock))
|
||||
task = js::oom::THREAD_TYPE_ASMJS;
|
||||
else if (HelperThreadState().canStartPromiseTask(lock))
|
||||
task = js::oom::THREAD_TYPE_PROMISE_TASK;
|
||||
else if (HelperThreadState().canStartParseTask(lock))
|
||||
task = js::oom::THREAD_TYPE_PARSE;
|
||||
else if (HelperThreadState().canStartCompressionTask(lock))
|
||||
task = js::oom::THREAD_TYPE_COMPRESS;
|
||||
else
|
||||
task = js::oom::THREAD_TYPE_NONE;
|
||||
|
||||
if (task != js::oom::THREAD_TYPE_NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
HelperThreadState().wait(lock, GlobalHelperThreadState::PRODUCER);
|
||||
}
|
||||
|
||||
if (ionCompile) {
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_ION);
|
||||
handleIonWorkload(lock);
|
||||
} else if (HelperThreadState().canStartWasmCompile(lock)) {
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_ASMJS);
|
||||
handleWasmWorkload(lock);
|
||||
} else if (HelperThreadState().canStartPromiseTask(lock)) {
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_PROMISE_TASK);
|
||||
handlePromiseTaskWorkload(lock);
|
||||
} else if (HelperThreadState().canStartParseTask(lock)) {
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_PARSE);
|
||||
handleParseWorkload(lock, stackLimit);
|
||||
} else if (HelperThreadState().canStartCompressionTask(lock)) {
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_COMPRESS);
|
||||
handleCompressionWorkload(lock);
|
||||
} else if (HelperThreadState().canStartGCHelperTask(lock)) {
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_GCHELPER);
|
||||
handleGCHelperWorkload(lock);
|
||||
} else if (HelperThreadState().canStartGCParallelTask(lock)) {
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_GCPARALLEL);
|
||||
js::oom::SetThreadType(task);
|
||||
switch (task) {
|
||||
case js::oom::THREAD_TYPE_GCPARALLEL:
|
||||
handleGCParallelWorkload(lock);
|
||||
} else {
|
||||
break;
|
||||
case js::oom::THREAD_TYPE_GCHELPER:
|
||||
handleGCHelperWorkload(lock);
|
||||
break;
|
||||
case js::oom::THREAD_TYPE_ION:
|
||||
handleIonWorkload(lock);
|
||||
break;
|
||||
case js::oom::THREAD_TYPE_ASMJS:
|
||||
handleWasmWorkload(lock);
|
||||
break;
|
||||
case js::oom::THREAD_TYPE_PROMISE_TASK:
|
||||
handlePromiseTaskWorkload(lock);
|
||||
break;
|
||||
case js::oom::THREAD_TYPE_PARSE:
|
||||
handleParseWorkload(lock, stackLimit);
|
||||
break;
|
||||
case js::oom::THREAD_TYPE_COMPRESS:
|
||||
handleCompressionWorkload(lock);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("No task to perform");
|
||||
}
|
||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ class GlobalHelperThreadState
|
||||
void waitForAllThreads();
|
||||
|
||||
template <typename T>
|
||||
bool checkTaskThreadLimit(size_t maxThreads) const;
|
||||
bool checkTaskThreadLimit(size_t maxThreads, bool isMaster = false) const;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ chromeos_dev_list="libbluetooth-dev libpulse-dev"
|
||||
# Packages need for development
|
||||
dev_list="apache2.2-bin bison curl elfutils fakeroot flex g++ gperf
|
||||
language-pack-fr libapache2-mod-php5 libasound2-dev libbz2-dev
|
||||
libcairo2-dev libcups2-dev libcurl4-gnutls-dev libdbus-glib-1-dev
|
||||
libcairo2-dev libcups2-dev libcurl4-gnutls-dev
|
||||
libelf-dev libgconf2-dev libgl1-mesa-dev libglib2.0-dev
|
||||
libglu1-mesa-dev libgnome-keyring-dev libgtk2.0-dev
|
||||
libkrb5-dev libnspr4-dev libnss3-dev libpam0g-dev libsctp-dev
|
||||
@@ -80,7 +80,7 @@ fi
|
||||
chromeos_lib_list="libpulse0 libbz2-1.0 libcurl4-gnutls-dev"
|
||||
|
||||
# Full list of required run-time libraries
|
||||
lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libcups2 libdbus-glib-1-2
|
||||
lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libcups2
|
||||
libexpat1 libfontconfig1 libfreetype6 libglib2.0-0 libgnome-keyring0
|
||||
libgtk2.0-0 libpam0g libpango1.0-0 libpcre3 libpixman-1-0
|
||||
libpng12-0 libstdc++6 libsqlite3-0 libudev0 libx11-6 libxau6 libxcb1
|
||||
@@ -89,7 +89,7 @@ lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libcups2 libdbus-glib-1-2
|
||||
$chromeos_lib_list"
|
||||
|
||||
# Debugging symbols for all of the run-time libraries
|
||||
dbg_list="libatk1.0-dbg libc6-dbg libcairo2-dbg libdbus-glib-1-2-dbg
|
||||
dbg_list="libatk1.0-dbg libc6-dbg libcairo2-dbg
|
||||
libfontconfig1-dbg libglib2.0-0-dbg libgtk2.0-0-dbg
|
||||
libpango1.0-0-dbg libpcre3-dbg libpixman-1-0-dbg
|
||||
libsqlite3-0-dbg
|
||||
|
||||
@@ -112,27 +112,6 @@
|
||||
],
|
||||
},
|
||||
], # targets
|
||||
}, { # chromeos==1
|
||||
'targets': [
|
||||
{
|
||||
# TODO(satorux): Remove this once dbus-glib clients are gone.
|
||||
'target_name': 'dbus-glib',
|
||||
'type': 'none',
|
||||
'direct_dependent_settings': {
|
||||
'cflags': [
|
||||
'<!@(<(pkg-config) --cflags dbus-glib-1)',
|
||||
],
|
||||
},
|
||||
'link_settings': {
|
||||
'ldflags': [
|
||||
'<!@(<(pkg-config) --libs-only-L --libs-only-other dbus-glib-1)',
|
||||
],
|
||||
'libraries': [
|
||||
'<!@(<(pkg-config) --libs-only-l dbus-glib-1)',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}]
|
||||
], # conditions
|
||||
'targets': [
|
||||
|
||||
@@ -61,12 +61,6 @@ config("common_inherited_config") {
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_have_dbus_glib) {
|
||||
pkg_config("dbus-glib") {
|
||||
packages = [ "dbus-glib-1" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("common_config") {
|
||||
cflags = []
|
||||
cflags_cc = []
|
||||
@@ -74,16 +68,6 @@ config("common_config") {
|
||||
defines = [ "WEBRTC_RESTRICT_LOGGING" ]
|
||||
}
|
||||
|
||||
if (rtc_have_dbus_glib) {
|
||||
defines += [ "HAVE_DBUS_GLIB" ]
|
||||
|
||||
# TODO(kjellander): Investigate this, it seems like include <dbus/dbus.h>
|
||||
# is still not found even if the execution of
|
||||
# build/config/linux/pkg-config.py dbus-glib-1 returns correct include
|
||||
# dirs on Linux.
|
||||
all_dependent_configs = [ "dbus-glib" ]
|
||||
}
|
||||
|
||||
if (build_with_chromium) {
|
||||
defines += [ "LOGGING_INSIDE_WEBRTC" ]
|
||||
} else {
|
||||
|
||||
@@ -426,10 +426,6 @@ static_library("rtc_base") {
|
||||
|
||||
if (is_linux) {
|
||||
sources += [
|
||||
"dbus.cc",
|
||||
"dbus.h",
|
||||
"libdbusglibsymboltable.cc",
|
||||
"libdbusglibsymboltable.h",
|
||||
"linuxfdwalk.c",
|
||||
"linuxfdwalk.h",
|
||||
]
|
||||
|
||||
@@ -204,8 +204,6 @@
|
||||
'crc32.h',
|
||||
'cryptstring.cc',
|
||||
'cryptstring.h',
|
||||
'dbus.cc',
|
||||
'dbus.h',
|
||||
'diskcache.cc',
|
||||
'diskcache.h',
|
||||
'diskcache_win32.cc',
|
||||
@@ -246,8 +244,6 @@
|
||||
'json.h',
|
||||
'latebindingsymboltable.cc',
|
||||
'latebindingsymboltable.h',
|
||||
'libdbusglibsymboltable.cc',
|
||||
'libdbusglibsymboltable.h',
|
||||
'linux.cc',
|
||||
'linux.h',
|
||||
'linuxfdwalk.c',
|
||||
@@ -456,8 +452,6 @@
|
||||
'bandwidthsmoother.h',
|
||||
'bind.h',
|
||||
'callback.h',
|
||||
'dbus.cc',
|
||||
'dbus.h',
|
||||
'diskcache_win32.cc',
|
||||
'diskcache_win32.h',
|
||||
'fileutils_mock.h',
|
||||
@@ -468,8 +462,6 @@
|
||||
'json.h',
|
||||
'latebindingsymboltable.cc',
|
||||
'latebindingsymboltable.h',
|
||||
'libdbusglibsymboltable.cc',
|
||||
'libdbusglibsymboltable.h',
|
||||
'linuxfdwalk.c',
|
||||
'linuxfdwalk.h',
|
||||
'x11windowpicker.cc',
|
||||
@@ -627,10 +619,6 @@
|
||||
},
|
||||
}, {
|
||||
'sources!': [
|
||||
'dbus.cc',
|
||||
'dbus.h',
|
||||
'libdbusglibsymboltable.cc',
|
||||
'libdbusglibsymboltable.h',
|
||||
'linuxfdwalk.c',
|
||||
],
|
||||
}],
|
||||
|
||||
@@ -1,400 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DBUS_GLIB
|
||||
|
||||
#include "webrtc/base/dbus.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Avoid static object construction/destruction on startup/shutdown.
|
||||
static pthread_once_t g_dbus_init_once = PTHREAD_ONCE_INIT;
|
||||
static LibDBusGlibSymbolTable *g_dbus_symbol = NULL;
|
||||
|
||||
// Releases DBus-Glib symbols.
|
||||
static void ReleaseDBusGlibSymbol() {
|
||||
if (g_dbus_symbol != NULL) {
|
||||
delete g_dbus_symbol;
|
||||
g_dbus_symbol = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Loads DBus-Glib symbols.
|
||||
static void InitializeDBusGlibSymbol() {
|
||||
// This is thread safe.
|
||||
if (NULL == g_dbus_symbol) {
|
||||
g_dbus_symbol = new LibDBusGlibSymbolTable();
|
||||
|
||||
// Loads dbus-glib
|
||||
if (NULL == g_dbus_symbol || !g_dbus_symbol->Load()) {
|
||||
LOG(LS_WARNING) << "Failed to load dbus-glib symbol table.";
|
||||
ReleaseDBusGlibSymbol();
|
||||
} else {
|
||||
// Nothing we can do if atexit() failed. Just ignore its returned value.
|
||||
atexit(ReleaseDBusGlibSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline static LibDBusGlibSymbolTable *GetSymbols() {
|
||||
return DBusMonitor::GetDBusGlibSymbolTable();
|
||||
}
|
||||
|
||||
// Implementation of class DBusSigMessageData
|
||||
DBusSigMessageData::DBusSigMessageData(DBusMessage *message)
|
||||
: TypedMessageData<DBusMessage *>(message) {
|
||||
GetSymbols()->dbus_message_ref()(data());
|
||||
}
|
||||
|
||||
DBusSigMessageData::~DBusSigMessageData() {
|
||||
GetSymbols()->dbus_message_unref()(data());
|
||||
}
|
||||
|
||||
// Implementation of class DBusSigFilter
|
||||
|
||||
// Builds a DBus filter string from given DBus path, interface and member.
|
||||
std::string DBusSigFilter::BuildFilterString(const std::string &path,
|
||||
const std::string &interface,
|
||||
const std::string &member) {
|
||||
std::string ret(DBUS_TYPE "='" DBUS_SIGNAL "'");
|
||||
if (!path.empty()) {
|
||||
ret += ("," DBUS_PATH "='");
|
||||
ret += path;
|
||||
ret += "'";
|
||||
}
|
||||
if (!interface.empty()) {
|
||||
ret += ("," DBUS_INTERFACE "='");
|
||||
ret += interface;
|
||||
ret += "'";
|
||||
}
|
||||
if (!member.empty()) {
|
||||
ret += ("," DBUS_MEMBER "='");
|
||||
ret += member;
|
||||
ret += "'";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Forwards the message to the given instance.
|
||||
DBusHandlerResult DBusSigFilter::DBusCallback(DBusConnection *dbus_conn,
|
||||
DBusMessage *message,
|
||||
void *instance) {
|
||||
ASSERT(instance);
|
||||
if (instance) {
|
||||
return static_cast<DBusSigFilter *>(instance)->Callback(message);
|
||||
}
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
// Posts a message to caller thread.
|
||||
DBusHandlerResult DBusSigFilter::Callback(DBusMessage *message) {
|
||||
if (caller_thread_) {
|
||||
caller_thread_->Post(this, DSM_SIGNAL, new DBusSigMessageData(message));
|
||||
}
|
||||
// Don't "eat" the message here. Let it pop up.
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
// From MessageHandler.
|
||||
void DBusSigFilter::OnMessage(Message *message) {
|
||||
if (message != NULL && DSM_SIGNAL == message->message_id) {
|
||||
DBusSigMessageData *msg =
|
||||
static_cast<DBusSigMessageData *>(message->pdata);
|
||||
if (msg) {
|
||||
ProcessSignal(msg->data());
|
||||
delete msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Definition of private class DBusMonitoringThread.
|
||||
// It creates a worker-thread to listen signals on DBus. The worker-thread will
|
||||
// be running in a priate GMainLoop forever until either Stop() has been invoked
|
||||
// or it hits an error.
|
||||
class DBusMonitor::DBusMonitoringThread : public rtc::Thread {
|
||||
public:
|
||||
explicit DBusMonitoringThread(DBusMonitor *monitor,
|
||||
GMainContext *context,
|
||||
GMainLoop *mainloop,
|
||||
std::vector<DBusSigFilter *> *filter_list)
|
||||
: monitor_(monitor),
|
||||
context_(context),
|
||||
mainloop_(mainloop),
|
||||
connection_(NULL),
|
||||
idle_source_(NULL),
|
||||
filter_list_(filter_list) {
|
||||
ASSERT(monitor_);
|
||||
ASSERT(context_);
|
||||
ASSERT(mainloop_);
|
||||
ASSERT(filter_list_);
|
||||
}
|
||||
|
||||
virtual ~DBusMonitoringThread() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
// Override virtual method of Thread. Context: worker-thread.
|
||||
virtual void Run() {
|
||||
ASSERT(NULL == connection_);
|
||||
|
||||
// Setup DBus connection and start monitoring.
|
||||
monitor_->OnMonitoringStatusChanged(DMS_INITIALIZING);
|
||||
if (!Setup()) {
|
||||
LOG(LS_ERROR) << "DBus monitoring setup failed.";
|
||||
monitor_->OnMonitoringStatusChanged(DMS_FAILED);
|
||||
CleanUp();
|
||||
return;
|
||||
}
|
||||
monitor_->OnMonitoringStatusChanged(DMS_RUNNING);
|
||||
g_main_loop_run(mainloop_);
|
||||
monitor_->OnMonitoringStatusChanged(DMS_STOPPED);
|
||||
|
||||
// Done normally. Clean up DBus connection.
|
||||
CleanUp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Override virtual method of Thread. Context: caller-thread.
|
||||
virtual void Stop() {
|
||||
ASSERT(NULL == idle_source_);
|
||||
// Add an idle source and let the gmainloop quit on idle.
|
||||
idle_source_ = g_idle_source_new();
|
||||
if (idle_source_) {
|
||||
g_source_set_callback(idle_source_, &Idle, this, NULL);
|
||||
g_source_attach(idle_source_, context_);
|
||||
} else {
|
||||
LOG(LS_ERROR) << "g_idle_source_new() failed.";
|
||||
QuitGMainloop(); // Try to quit anyway.
|
||||
}
|
||||
|
||||
Thread::Stop(); // Wait for the thread.
|
||||
}
|
||||
|
||||
private:
|
||||
// Registers all DBus filters.
|
||||
void RegisterAllFilters() {
|
||||
ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()(
|
||||
connection_));
|
||||
|
||||
for (std::vector<DBusSigFilter *>::iterator it = filter_list_->begin();
|
||||
it != filter_list_->end(); ++it) {
|
||||
DBusSigFilter *filter = (*it);
|
||||
if (!filter) {
|
||||
LOG(LS_ERROR) << "DBusSigFilter list corrupted.";
|
||||
continue;
|
||||
}
|
||||
|
||||
GetSymbols()->dbus_bus_add_match()(
|
||||
GetSymbols()->dbus_g_connection_get_connection()(connection_),
|
||||
filter->filter().c_str(), NULL);
|
||||
|
||||
if (!GetSymbols()->dbus_connection_add_filter()(
|
||||
GetSymbols()->dbus_g_connection_get_connection()(connection_),
|
||||
&DBusSigFilter::DBusCallback, filter, NULL)) {
|
||||
LOG(LS_ERROR) << "dbus_connection_add_filter() failed."
|
||||
<< "Filter: " << filter->filter();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unregisters all DBus filters.
|
||||
void UnRegisterAllFilters() {
|
||||
ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()(
|
||||
connection_));
|
||||
|
||||
for (std::vector<DBusSigFilter *>::iterator it = filter_list_->begin();
|
||||
it != filter_list_->end(); ++it) {
|
||||
DBusSigFilter *filter = (*it);
|
||||
if (!filter) {
|
||||
LOG(LS_ERROR) << "DBusSigFilter list corrupted.";
|
||||
continue;
|
||||
}
|
||||
GetSymbols()->dbus_connection_remove_filter()(
|
||||
GetSymbols()->dbus_g_connection_get_connection()(connection_),
|
||||
&DBusSigFilter::DBusCallback, filter);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets up the monitoring thread.
|
||||
bool Setup() {
|
||||
g_main_context_push_thread_default(context_);
|
||||
|
||||
// Start connection to dbus.
|
||||
// If dbus daemon is not running, returns false immediately.
|
||||
connection_ = GetSymbols()->dbus_g_bus_get_private()(monitor_->type_,
|
||||
context_, NULL);
|
||||
if (NULL == connection_) {
|
||||
LOG(LS_ERROR) << "dbus_g_bus_get_private() unable to get connection.";
|
||||
return false;
|
||||
}
|
||||
if (NULL == GetSymbols()->dbus_g_connection_get_connection()(connection_)) {
|
||||
LOG(LS_ERROR) << "dbus_g_connection_get_connection() returns NULL. "
|
||||
<< "DBus daemon is probably not running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Application don't exit if DBus daemon die.
|
||||
GetSymbols()->dbus_connection_set_exit_on_disconnect()(
|
||||
GetSymbols()->dbus_g_connection_get_connection()(connection_), FALSE);
|
||||
|
||||
// Connect all filters.
|
||||
RegisterAllFilters();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cleans up the monitoring thread.
|
||||
void CleanUp() {
|
||||
if (idle_source_) {
|
||||
// We did an attach() with the GSource, so we need to destroy() it.
|
||||
g_source_destroy(idle_source_);
|
||||
// We need to unref() the GSource to end the last reference we got.
|
||||
g_source_unref(idle_source_);
|
||||
idle_source_ = NULL;
|
||||
}
|
||||
if (connection_) {
|
||||
if (GetSymbols()->dbus_g_connection_get_connection()(connection_)) {
|
||||
UnRegisterAllFilters();
|
||||
GetSymbols()->dbus_connection_close()(
|
||||
GetSymbols()->dbus_g_connection_get_connection()(connection_));
|
||||
}
|
||||
GetSymbols()->dbus_g_connection_unref()(connection_);
|
||||
connection_ = NULL;
|
||||
}
|
||||
g_main_loop_unref(mainloop_);
|
||||
mainloop_ = NULL;
|
||||
g_main_context_unref(context_);
|
||||
context_ = NULL;
|
||||
}
|
||||
|
||||
// Handles callback on Idle. We only add this source when ready to stop.
|
||||
static gboolean Idle(gpointer data) {
|
||||
static_cast<DBusMonitoringThread *>(data)->QuitGMainloop();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// We only hit this when ready to quit.
|
||||
void QuitGMainloop() {
|
||||
g_main_loop_quit(mainloop_);
|
||||
}
|
||||
|
||||
DBusMonitor *monitor_;
|
||||
|
||||
GMainContext *context_;
|
||||
GMainLoop *mainloop_;
|
||||
DBusGConnection *connection_;
|
||||
GSource *idle_source_;
|
||||
|
||||
std::vector<DBusSigFilter *> *filter_list_;
|
||||
};
|
||||
|
||||
// Implementation of class DBusMonitor
|
||||
|
||||
// Returns DBus-Glib symbol handle. Initialize it first if hasn't.
|
||||
LibDBusGlibSymbolTable *DBusMonitor::GetDBusGlibSymbolTable() {
|
||||
// This is multi-thread safe.
|
||||
pthread_once(&g_dbus_init_once, InitializeDBusGlibSymbol);
|
||||
|
||||
return g_dbus_symbol;
|
||||
};
|
||||
|
||||
// Creates an instance of DBusMonitor
|
||||
DBusMonitor *DBusMonitor::Create(DBusBusType type) {
|
||||
if (NULL == DBusMonitor::GetDBusGlibSymbolTable()) {
|
||||
return NULL;
|
||||
}
|
||||
return new DBusMonitor(type);
|
||||
}
|
||||
|
||||
DBusMonitor::DBusMonitor(DBusBusType type)
|
||||
: type_(type),
|
||||
status_(DMS_NOT_INITIALIZED),
|
||||
monitoring_thread_(NULL) {
|
||||
ASSERT(type_ == DBUS_BUS_SYSTEM || type_ == DBUS_BUS_SESSION);
|
||||
}
|
||||
|
||||
DBusMonitor::~DBusMonitor() {
|
||||
StopMonitoring();
|
||||
}
|
||||
|
||||
bool DBusMonitor::AddFilter(DBusSigFilter *filter) {
|
||||
if (monitoring_thread_) {
|
||||
return false;
|
||||
}
|
||||
if (!filter) {
|
||||
return false;
|
||||
}
|
||||
filter_list_.push_back(filter);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBusMonitor::StartMonitoring() {
|
||||
if (!monitoring_thread_) {
|
||||
g_type_init();
|
||||
// g_thread_init API is deprecated since glib 2.31.0, see release note:
|
||||
// http://mail.gnome.org/archives/gnome-announce-list/2011-October/msg00041.html
|
||||
#if !GLIB_CHECK_VERSION(2, 31, 0)
|
||||
g_thread_init(NULL);
|
||||
#endif
|
||||
GetSymbols()->dbus_g_thread_init()();
|
||||
|
||||
GMainContext *context = g_main_context_new();
|
||||
if (NULL == context) {
|
||||
LOG(LS_ERROR) << "g_main_context_new() failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
GMainLoop *mainloop = g_main_loop_new(context, FALSE);
|
||||
if (NULL == mainloop) {
|
||||
LOG(LS_ERROR) << "g_main_loop_new() failed.";
|
||||
g_main_context_unref(context);
|
||||
return false;
|
||||
}
|
||||
|
||||
monitoring_thread_ = new DBusMonitoringThread(this, context, mainloop,
|
||||
&filter_list_);
|
||||
if (monitoring_thread_ == NULL) {
|
||||
LOG(LS_ERROR) << "Failed to create DBus monitoring thread.";
|
||||
g_main_context_unref(context);
|
||||
g_main_loop_unref(mainloop);
|
||||
return false;
|
||||
}
|
||||
monitoring_thread_->Start();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBusMonitor::StopMonitoring() {
|
||||
if (monitoring_thread_) {
|
||||
monitoring_thread_->Stop();
|
||||
monitoring_thread_ = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DBusMonitor::DBusMonitorStatus DBusMonitor::GetStatus() {
|
||||
return status_;
|
||||
}
|
||||
|
||||
void DBusMonitor::OnMonitoringStatusChanged(DBusMonitorStatus status) {
|
||||
status_ = status;
|
||||
}
|
||||
|
||||
#undef LATE
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // HAVE_DBUS_GLIB
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_DBUS_H_
|
||||
#define WEBRTC_BASE_DBUS_H_
|
||||
|
||||
#ifdef HAVE_DBUS_GLIB
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/libdbusglibsymboltable.h"
|
||||
#include "webrtc/base/messagehandler.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
#define DBUS_TYPE "type"
|
||||
#define DBUS_SIGNAL "signal"
|
||||
#define DBUS_PATH "path"
|
||||
#define DBUS_INTERFACE "interface"
|
||||
#define DBUS_MEMBER "member"
|
||||
|
||||
#ifdef CHROMEOS
|
||||
#define CROS_PM_PATH "/"
|
||||
#define CROS_PM_INTERFACE "org.chromium.PowerManager"
|
||||
#define CROS_SIG_POWERCHANGED "PowerStateChanged"
|
||||
#define CROS_VALUE_SLEEP "mem"
|
||||
#define CROS_VALUE_RESUME "on"
|
||||
#else
|
||||
#define UP_PATH "/org/freedesktop/UPower"
|
||||
#define UP_INTERFACE "org.freedesktop.UPower"
|
||||
#define UP_SIG_SLEEPING "Sleeping"
|
||||
#define UP_SIG_RESUMING "Resuming"
|
||||
#endif // CHROMEOS
|
||||
|
||||
// Wraps a DBus messages.
|
||||
class DBusSigMessageData : public TypedMessageData<DBusMessage *> {
|
||||
public:
|
||||
explicit DBusSigMessageData(DBusMessage *message);
|
||||
~DBusSigMessageData();
|
||||
};
|
||||
|
||||
// DBusSigFilter is an abstract class that defines the interface of DBus
|
||||
// signal handling.
|
||||
// The subclasses implement ProcessSignal() for various purposes.
|
||||
// When a DBus signal comes, a DSM_SIGNAL message is posted to the caller thread
|
||||
// which will then invokes ProcessSignal().
|
||||
class DBusSigFilter : protected MessageHandler {
|
||||
public:
|
||||
enum DBusSigMessage { DSM_SIGNAL };
|
||||
|
||||
// This filter string should ususally come from BuildFilterString()
|
||||
explicit DBusSigFilter(const std::string &filter)
|
||||
: caller_thread_(Thread::Current()), filter_(filter) {
|
||||
}
|
||||
|
||||
// Builds a DBus monitor filter string from given DBus path, interface, and
|
||||
// member.
|
||||
// See http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html
|
||||
static std::string BuildFilterString(const std::string &path,
|
||||
const std::string &interface,
|
||||
const std::string &member);
|
||||
|
||||
// Handles callback on DBus messages by DBus system.
|
||||
static DBusHandlerResult DBusCallback(DBusConnection *dbus_conn,
|
||||
DBusMessage *message,
|
||||
void *instance);
|
||||
|
||||
// Handles callback on DBus messages to each DBusSigFilter instance.
|
||||
DBusHandlerResult Callback(DBusMessage *message);
|
||||
|
||||
// From MessageHandler.
|
||||
virtual void OnMessage(Message *message);
|
||||
|
||||
// Returns the DBus monitor filter string.
|
||||
const std::string &filter() const { return filter_; }
|
||||
|
||||
private:
|
||||
// On caller thread.
|
||||
virtual void ProcessSignal(DBusMessage *message) = 0;
|
||||
|
||||
Thread *caller_thread_;
|
||||
const std::string filter_;
|
||||
};
|
||||
|
||||
// DBusMonitor is a class for DBus signal monitoring.
|
||||
//
|
||||
// The caller-thread calls AddFilter() first to add the signals that it wants to
|
||||
// monitor and then calls StartMonitoring() to start the monitoring.
|
||||
// This will create a worker-thread which listens on DBus connection and sends
|
||||
// DBus signals back through the callback.
|
||||
// The worker-thread will be running forever until either StopMonitoring() is
|
||||
// called from the caller-thread or the worker-thread hit some error.
|
||||
//
|
||||
// Programming model:
|
||||
// 1. Caller-thread: Creates an object of DBusMonitor.
|
||||
// 2. Caller-thread: Calls DBusMonitor::AddFilter() one or several times.
|
||||
// 3. Caller-thread: StartMonitoring().
|
||||
// ...
|
||||
// 4. Worker-thread: DBus signal recieved. Post a message to caller-thread.
|
||||
// 5. Caller-thread: DBusFilterBase::ProcessSignal() is invoked.
|
||||
// ...
|
||||
// 6. Caller-thread: StopMonitoring().
|
||||
//
|
||||
// Assumption:
|
||||
// AddFilter(), StartMonitoring(), and StopMonitoring() methods are called by
|
||||
// a single thread. Hence, there is no need to make them thread safe.
|
||||
class DBusMonitor {
|
||||
public:
|
||||
// Status of DBus monitoring.
|
||||
enum DBusMonitorStatus {
|
||||
DMS_NOT_INITIALIZED, // Not initialized.
|
||||
DMS_INITIALIZING, // Initializing the monitoring thread.
|
||||
DMS_RUNNING, // Monitoring.
|
||||
DMS_STOPPED, // Not monitoring. Stopped normally.
|
||||
DMS_FAILED, // Not monitoring. Failed.
|
||||
};
|
||||
|
||||
// Returns the DBus-Glib symbol table.
|
||||
// We should only use this function to access DBus-Glib symbols.
|
||||
static LibDBusGlibSymbolTable *GetDBusGlibSymbolTable();
|
||||
|
||||
// Creates an instance of DBusMonitor.
|
||||
static DBusMonitor *Create(DBusBusType type);
|
||||
~DBusMonitor();
|
||||
|
||||
// Adds a filter to DBusMonitor.
|
||||
bool AddFilter(DBusSigFilter *filter);
|
||||
|
||||
// Starts DBus message monitoring.
|
||||
bool StartMonitoring();
|
||||
|
||||
// Stops DBus message monitoring.
|
||||
bool StopMonitoring();
|
||||
|
||||
// Gets the status of DBus monitoring.
|
||||
DBusMonitorStatus GetStatus();
|
||||
|
||||
private:
|
||||
// Forward declaration. Defined in the .cc file.
|
||||
class DBusMonitoringThread;
|
||||
|
||||
explicit DBusMonitor(DBusBusType type);
|
||||
|
||||
// Updates status_ when monitoring status has changed.
|
||||
void OnMonitoringStatusChanged(DBusMonitorStatus status);
|
||||
|
||||
DBusBusType type_;
|
||||
DBusMonitorStatus status_;
|
||||
DBusMonitoringThread *monitoring_thread_;
|
||||
std::vector<DBusSigFilter *> filter_list_;
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // HAVE_DBUS_GLIB
|
||||
|
||||
#endif // WEBRTC_BASE_DBUS_H_
|
||||
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DBUS_GLIB
|
||||
|
||||
#include "webrtc/base/dbus.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
#define SIG_NAME "NameAcquired"
|
||||
|
||||
static const uint32_t kTimeoutMs = 5000U;
|
||||
|
||||
class DBusSigFilterTest : public DBusSigFilter {
|
||||
public:
|
||||
// DBusSigFilterTest listens on DBus service itself for "NameAcquired" signal.
|
||||
// This signal should be received when the application connects to DBus
|
||||
// service and gains ownership of a name.
|
||||
// http://dbus.freedesktop.org/doc/dbus-specification.html
|
||||
DBusSigFilterTest()
|
||||
: DBusSigFilter(GetFilter()),
|
||||
message_received_(false) {
|
||||
}
|
||||
|
||||
bool MessageReceived() {
|
||||
return message_received_;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string GetFilter() {
|
||||
return rtc::DBusSigFilter::BuildFilterString("", "", SIG_NAME);
|
||||
}
|
||||
|
||||
// Implement virtual method of DBusSigFilter. On caller thread.
|
||||
virtual void ProcessSignal(DBusMessage *message) {
|
||||
EXPECT_TRUE(message != NULL);
|
||||
message_received_ = true;
|
||||
}
|
||||
|
||||
bool message_received_;
|
||||
};
|
||||
|
||||
TEST(DBusMonitorTest, StartStopStartStop) {
|
||||
DBusSigFilterTest filter;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
|
||||
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
if (monitor) {
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter));
|
||||
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_NOT_INITIALIZED);
|
||||
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_RUNNING);
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
|
||||
}
|
||||
}
|
||||
|
||||
// DBusMonitorTest listens on DBus service itself for "NameAcquired" signal.
|
||||
// This signal should be received when the application connects to DBus
|
||||
// service and gains ownership of a name.
|
||||
// This test is to make sure that we capture the "NameAcquired" signal.
|
||||
TEST(DBusMonitorTest, ReceivedNameAcquiredSignal) {
|
||||
DBusSigFilterTest filter;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
|
||||
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
if (monitor) {
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter));
|
||||
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
|
||||
EXPECT_TRUE_WAIT(filter.MessageReceived(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBusMonitorTest, ConcurrentMonitors) {
|
||||
DBusSigFilterTest filter1;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor1;
|
||||
monitor1.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
if (monitor1) {
|
||||
EXPECT_TRUE(monitor1->AddFilter(&filter1));
|
||||
DBusSigFilterTest filter2;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor2;
|
||||
monitor2.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
EXPECT_TRUE(monitor2->AddFilter(&filter2));
|
||||
|
||||
EXPECT_TRUE(monitor1->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor1->GetStatus(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor2->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor2->GetStatus(), kTimeoutMs);
|
||||
|
||||
EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor2->StopMonitoring());
|
||||
EXPECT_EQ(monitor2->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
|
||||
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor1->StopMonitoring());
|
||||
EXPECT_EQ(monitor1->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBusMonitorTest, ConcurrentFilters) {
|
||||
DBusSigFilterTest filter1;
|
||||
DBusSigFilterTest filter2;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
|
||||
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
if (monitor) {
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter1));
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter2));
|
||||
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
|
||||
|
||||
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
|
||||
EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs);
|
||||
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBusMonitorTest, NoAddFilterIfRunning) {
|
||||
DBusSigFilterTest filter1;
|
||||
DBusSigFilterTest filter2;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
|
||||
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
if (monitor) {
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter1));
|
||||
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
|
||||
EXPECT_FALSE(monitor->AddFilter(&filter2));
|
||||
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBusMonitorTest, AddFilterAfterStop) {
|
||||
DBusSigFilterTest filter1;
|
||||
DBusSigFilterTest filter2;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
|
||||
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
if (monitor) {
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter1));
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
|
||||
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter2));
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
|
||||
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
|
||||
EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs);
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBusMonitorTest, StopRightAfterStart) {
|
||||
DBusSigFilterTest filter;
|
||||
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
|
||||
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
|
||||
if (monitor) {
|
||||
EXPECT_TRUE(monitor->AddFilter(&filter));
|
||||
|
||||
EXPECT_TRUE(monitor->StartMonitoring());
|
||||
EXPECT_TRUE(monitor->StopMonitoring());
|
||||
|
||||
// Stop the monitoring thread right after it had been started.
|
||||
// If the monitoring thread got a chance to receive a DBus signal, it would
|
||||
// post a message to the main thread and signal the main thread wakeup.
|
||||
// This message will be cleaned out automatically when the filter get
|
||||
// destructed. Here we also consume the wakeup signal (if there is one) so
|
||||
// that the testing (main) thread is reset to a clean state.
|
||||
rtc::Thread::Current()->ProcessMessages(1);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "DBus Monitor not started.";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBusSigFilter, BuildFilterString) {
|
||||
EXPECT_EQ(DBusSigFilter::BuildFilterString("", "", ""),
|
||||
(DBUS_TYPE "='" DBUS_SIGNAL "'"));
|
||||
EXPECT_EQ(DBusSigFilter::BuildFilterString("p", "", ""),
|
||||
(DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p'"));
|
||||
EXPECT_EQ(DBusSigFilter::BuildFilterString("p","i", ""),
|
||||
(DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p',"
|
||||
DBUS_INTERFACE "='i'"));
|
||||
EXPECT_EQ(DBusSigFilter::BuildFilterString("p","i","m"),
|
||||
(DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p',"
|
||||
DBUS_INTERFACE "='i'," DBUS_MEMBER "='m'"));
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // HAVE_DBUS_GLIB
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DBUS_GLIB
|
||||
|
||||
#include "webrtc/base/libdbusglibsymboltable.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBDBUS_GLIB_CLASS_NAME
|
||||
#define LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST LIBDBUS_GLIB_SYMBOLS_LIST
|
||||
#define LATE_BINDING_SYMBOL_TABLE_DLL_NAME "libdbus-glib-1.so.2"
|
||||
#include "webrtc/base/latebindingsymboltable.cc.def"
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // HAVE_DBUS_GLIB
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_
|
||||
#define WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_
|
||||
|
||||
#ifdef HAVE_DBUS_GLIB
|
||||
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
|
||||
#include "webrtc/base/latebindingsymboltable.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
#define LIBDBUS_GLIB_CLASS_NAME LibDBusGlibSymbolTable
|
||||
// The libdbus-glib symbols we need, as an X-Macro list.
|
||||
// This list must contain precisely every libdbus-glib function that is used in
|
||||
// dbus.cc.
|
||||
#define LIBDBUS_GLIB_SYMBOLS_LIST \
|
||||
X(dbus_bus_add_match) \
|
||||
X(dbus_connection_add_filter) \
|
||||
X(dbus_connection_close) \
|
||||
X(dbus_connection_remove_filter) \
|
||||
X(dbus_connection_set_exit_on_disconnect) \
|
||||
X(dbus_g_bus_get) \
|
||||
X(dbus_g_bus_get_private) \
|
||||
X(dbus_g_connection_get_connection) \
|
||||
X(dbus_g_connection_unref) \
|
||||
X(dbus_g_thread_init) \
|
||||
X(dbus_message_get_interface) \
|
||||
X(dbus_message_get_member) \
|
||||
X(dbus_message_get_path) \
|
||||
X(dbus_message_get_type) \
|
||||
X(dbus_message_iter_get_arg_type) \
|
||||
X(dbus_message_iter_get_basic) \
|
||||
X(dbus_message_iter_init) \
|
||||
X(dbus_message_ref) \
|
||||
X(dbus_message_unref)
|
||||
|
||||
#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBDBUS_GLIB_CLASS_NAME
|
||||
#define LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST LIBDBUS_GLIB_SYMBOLS_LIST
|
||||
#include "webrtc/base/latebindingsymboltable.h.def"
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // HAVE_DBUS_GLIB
|
||||
|
||||
#endif // WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_
|
||||
@@ -108,9 +108,6 @@
|
||||
'build_protobuf%': 1,
|
||||
'build_ssl%': 1,
|
||||
|
||||
# Disable by default
|
||||
'have_dbus_glib%': 0,
|
||||
|
||||
# Make it possible to provide custom locations for some libraries.
|
||||
'libvpx_dir%': '<(DEPTH)/third_party/libvpx_new',
|
||||
'libyuv_dir%': '<(DEPTH)/third_party/libyuv',
|
||||
@@ -237,14 +234,6 @@
|
||||
'WEBRTC_MOZILLA_BUILD',
|
||||
],
|
||||
}],
|
||||
['have_dbus_glib==1', {
|
||||
'defines': [
|
||||
'HAVE_DBUS_GLIB',
|
||||
],
|
||||
'cflags': [
|
||||
'<!@(pkg-config --cflags dbus-glib-1)',
|
||||
],
|
||||
}],
|
||||
['rtc_relative_path==1', {
|
||||
'defines': ['EXPAT_RELATIVE_PATH',],
|
||||
}],
|
||||
@@ -539,4 +528,3 @@
|
||||
},
|
||||
}, # target_defaults
|
||||
}
|
||||
|
||||
|
||||
@@ -44,9 +44,6 @@ declare_args() {
|
||||
rtc_build_opus = true
|
||||
rtc_build_ssl = true
|
||||
|
||||
# Disable by default.
|
||||
rtc_have_dbus_glib = false
|
||||
|
||||
# Enable to use the Mozilla internal settings.
|
||||
build_with_mozilla = false
|
||||
|
||||
|
||||
@@ -54,6 +54,6 @@ if CONFIG['NECKO_WIFI_DBUS']:
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
if CONFIG['NECKO_WIFI_DBUS']:
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
@@ -2409,7 +2409,6 @@ then
|
||||
if test "$MOZ_ENABLE_DBUS"
|
||||
then
|
||||
PKG_CHECK_MODULES(MOZ_DBUS, dbus-1 >= $DBUS_VERSION)
|
||||
PKG_CHECK_MODULES(MOZ_DBUS_GLIB, dbus-glib-1 >= $DBUS_VERSION)
|
||||
AC_DEFINE(MOZ_ENABLE_DBUS)
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -2082,6 +2082,45 @@ static const NameConstraintParams NAME_CONSTRAINT_PARAMS[] =
|
||||
Result::ERROR_BAD_DER, Result::ERROR_BAD_DER
|
||||
},
|
||||
|
||||
// Wildcard SANs have subtle outcomes.
|
||||
{ ByteString(), DNSName("*.example.com"),
|
||||
GeneralSubtree(DNSName(".example.com")),
|
||||
Success,
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
},
|
||||
{ ByteString(), DNSName("*.example.com"),
|
||||
GeneralSubtree(DNSName("example.com")),
|
||||
Success,
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
},
|
||||
// A certificate with a wildcard SAN entry like `*.example.com` can't be
|
||||
// issued by a CA with a DNSName name constraint entry like `foo.example.com`
|
||||
// in either the permitted or excluded subtrees. If in the permitted subtree,
|
||||
// the certificate would be valid for `bar.example.com`, which would violate
|
||||
// the constraint. If in the excluded subtree, the certificate would be valid
|
||||
// for `foo.example.com`, which would violate the constraint.
|
||||
{ ByteString(), DNSName("*.example.com"),
|
||||
GeneralSubtree(DNSName("foo.example.com")),
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE,
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
},
|
||||
{ ByteString(), DNSName("*.foo.example.com"),
|
||||
GeneralSubtree(DNSName("example.com")),
|
||||
Success,
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
},
|
||||
{ ByteString(), DNSName("*.example.com"),
|
||||
GeneralSubtree(DNSName("foo.example.org")),
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE,
|
||||
Success
|
||||
},
|
||||
// `*invalid.example.com` is an invalid presented DNSID.
|
||||
{ ByteString(), DNSName("*invalid.example.com"),
|
||||
GeneralSubtree(DNSName("invalid.example.com")),
|
||||
Result::ERROR_BAD_DER,
|
||||
Result::ERROR_BAD_DER
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Basic IP Address constraints (non-CN-ID)
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
/* Copyright 2014 Mozilla Contributors
|
||||
* Copyright 2026 Moonchild Productions
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -170,6 +171,12 @@ enum class IDRole
|
||||
NameConstraint = 2,
|
||||
};
|
||||
|
||||
enum class NameConstraintsSubtrees : uint8_t
|
||||
{
|
||||
permittedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0,
|
||||
excludedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 1
|
||||
};
|
||||
|
||||
enum class AllowWildcards { No = 0, Yes = 1 };
|
||||
|
||||
// DNSName constraints implicitly allow subdomain matching when there is no
|
||||
@@ -182,16 +189,22 @@ enum class AllowDotlessSubdomainMatches { No = 0, Yes = 1 };
|
||||
bool IsValidDNSID(Input hostname, IDRole idRole,
|
||||
AllowWildcards allowWildcards);
|
||||
|
||||
// `subtreesType` is relevant only when `referenceDNSIDRole` is
|
||||
// `IDRole::NameConstraint`.
|
||||
Result MatchPresentedDNSIDWithReferenceDNSID(
|
||||
Input presentedDNSID,
|
||||
AllowWildcards allowWildcards,
|
||||
AllowDotlessSubdomainMatches allowDotlessSubdomainMatches,
|
||||
IDRole referenceDNSIDRole,
|
||||
/*optional*/ const NameConstraintsSubtrees* subtreesType,
|
||||
Input referenceDNSID,
|
||||
/*out*/ bool& matches);
|
||||
|
||||
// `subtreesType` is relevant only when `referenceDNSIDRole` is
|
||||
// `IDRole::NameConstraint`.
|
||||
Result MatchPresentedRFC822NameWithReferenceRFC822Name(
|
||||
Input presentedRFC822Name, IDRole referenceRFC822NameRole,
|
||||
/*optional*/ const NameConstraintsSubtrees* subtreesType,
|
||||
Input referenceRFC822Name, /*out*/ bool& matches);
|
||||
|
||||
} // namespace
|
||||
@@ -210,7 +223,7 @@ MatchPresentedDNSIDWithReferenceDNSID(Input presentedDNSID,
|
||||
return MatchPresentedDNSIDWithReferenceDNSID(
|
||||
presentedDNSID, AllowWildcards::Yes,
|
||||
AllowDotlessSubdomainMatches::Yes, IDRole::ReferenceID,
|
||||
referenceDNSID, matches);
|
||||
nullptr, referenceDNSID, matches);
|
||||
}
|
||||
|
||||
// Verify that the given end-entity cert, which is assumed to have been already
|
||||
@@ -694,7 +707,7 @@ MatchPresentedIDWithReferenceID(GeneralNameType presentedIDType,
|
||||
rv = MatchPresentedDNSIDWithReferenceDNSID(
|
||||
presentedID, AllowWildcards::Yes,
|
||||
AllowDotlessSubdomainMatches::Yes, IDRole::ReferenceID,
|
||||
referenceID, foundMatch);
|
||||
nullptr, referenceID, foundMatch);
|
||||
break;
|
||||
|
||||
case GeneralNameType::iPAddress:
|
||||
@@ -704,7 +717,7 @@ MatchPresentedIDWithReferenceID(GeneralNameType presentedIDType,
|
||||
|
||||
case GeneralNameType::rfc822Name:
|
||||
rv = MatchPresentedRFC822NameWithReferenceRFC822Name(
|
||||
presentedID, IDRole::ReferenceID, referenceID, foundMatch);
|
||||
presentedID, IDRole::ReferenceID, nullptr, referenceID, foundMatch);
|
||||
break;
|
||||
|
||||
case GeneralNameType::directoryName:
|
||||
@@ -730,12 +743,6 @@ MatchPresentedIDWithReferenceID(GeneralNameType presentedIDType,
|
||||
return Success;
|
||||
}
|
||||
|
||||
enum class NameConstraintsSubtrees : uint8_t
|
||||
{
|
||||
permittedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0,
|
||||
excludedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 1
|
||||
};
|
||||
|
||||
Result CheckPresentedIDConformsToNameConstraintsSubtrees(
|
||||
GeneralNameType presentedIDType,
|
||||
Input presentedID,
|
||||
@@ -849,7 +856,7 @@ CheckPresentedIDConformsToNameConstraintsSubtrees(
|
||||
rv = MatchPresentedDNSIDWithReferenceDNSID(
|
||||
presentedID, AllowWildcards::Yes,
|
||||
AllowDotlessSubdomainMatches::Yes, IDRole::NameConstraint,
|
||||
base, matches);
|
||||
&subtreesType, base, matches);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
@@ -874,7 +881,7 @@ CheckPresentedIDConformsToNameConstraintsSubtrees(
|
||||
|
||||
case GeneralNameType::rfc822Name:
|
||||
rv = MatchPresentedRFC822NameWithReferenceRFC822Name(
|
||||
presentedID, IDRole::NameConstraint, base, matches);
|
||||
presentedID, IDRole::NameConstraint, &subtreesType, base, matches);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
@@ -1057,6 +1064,7 @@ MatchPresentedDNSIDWithReferenceDNSID(
|
||||
AllowWildcards allowWildcards,
|
||||
AllowDotlessSubdomainMatches allowDotlessSubdomainMatches,
|
||||
IDRole referenceDNSIDRole,
|
||||
/*optional*/ const NameConstraintsSubtrees* subtreesType,
|
||||
Input referenceDNSID,
|
||||
/*out*/ bool& matches)
|
||||
{
|
||||
@@ -1147,18 +1155,28 @@ MatchPresentedDNSIDWithReferenceDNSID(
|
||||
return NotReached("Skipping '*' failed",
|
||||
Result::FATAL_ERROR_LIBRARY_FAILURE);
|
||||
}
|
||||
do {
|
||||
// This will happen if reference is a single, relative label
|
||||
if (reference.AtEnd()) {
|
||||
matches = false;
|
||||
return Success;
|
||||
}
|
||||
uint8_t referenceByte;
|
||||
if (reference.Read(referenceByte) != Success) {
|
||||
return NotReached("invalid reference ID",
|
||||
Result::FATAL_ERROR_INVALID_ARGS);
|
||||
}
|
||||
} while (!reference.Peek('.'));
|
||||
// For the permittedSubtrees of a name constraint, wildcard presented
|
||||
// DNSIDs of the form `*.example.com` only match if the name constraint is
|
||||
// of the form `.example.com` or `example.com`. To put it another way, a
|
||||
// permittedSubtrees of `foo.example.com` does not match a wildcard
|
||||
// presented DNSID of `*.example.com`, because in that case, the
|
||||
// certificate could be valid for `bar.example.com`, which does not match
|
||||
// the name constraint.
|
||||
if (referenceDNSIDRole != IDRole::NameConstraint ||
|
||||
(subtreesType && *subtreesType != NameConstraintsSubtrees::permittedSubtrees)) {
|
||||
do {
|
||||
// This will happen if reference is a single, relative label
|
||||
if (reference.AtEnd()) {
|
||||
matches = false;
|
||||
return Success;
|
||||
}
|
||||
uint8_t referenceByte;
|
||||
if (reference.Read(referenceByte) != Success) {
|
||||
return NotReached("invalid reference ID",
|
||||
Result::FATAL_ERROR_INVALID_ARGS);
|
||||
}
|
||||
} while (!reference.Peek('.'));
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@@ -1515,9 +1533,12 @@ IsValidRFC822Name(Input input)
|
||||
}
|
||||
}
|
||||
|
||||
// `subtreesType` is relevant only when `referenceRFC822NameRole` is
|
||||
// `IDRole::NameConstraint`.
|
||||
Result
|
||||
MatchPresentedRFC822NameWithReferenceRFC822Name(Input presentedRFC822Name,
|
||||
IDRole referenceRFC822NameRole,
|
||||
/*optional*/ const NameConstraintsSubtrees* subtreesType,
|
||||
Input referenceRFC822Name,
|
||||
/*out*/ bool& matches)
|
||||
{
|
||||
@@ -1562,6 +1583,7 @@ MatchPresentedRFC822NameWithReferenceRFC822Name(Input presentedRFC822Name,
|
||||
return MatchPresentedDNSIDWithReferenceDNSID(
|
||||
presentedDNSID, AllowWildcards::No,
|
||||
AllowDotlessSubdomainMatches::No, IDRole::NameConstraint,
|
||||
subtreesType,
|
||||
referenceRFC822Name, matches);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ RUN apt-get update && apt-get install -y --force-yes \
|
||||
libcanberra-pulse \
|
||||
libcurl4-openssl-dev \
|
||||
libdbus-1-dev \
|
||||
libdbus-glib-1-dev \
|
||||
libdrm-intel1:i386 \
|
||||
libdrm-nouveau1a:i386 \
|
||||
libdrm-radeon1:i386 \
|
||||
|
||||
@@ -50,10 +50,6 @@ install check-devel.i686
|
||||
install check-devel.x86_64
|
||||
install check.i686
|
||||
install check.x86_64
|
||||
install dbus-glib-devel.i686
|
||||
install dbus-glib-devel.x86_64
|
||||
install dbus-glib.i686
|
||||
install dbus-glib.x86_64
|
||||
install fontconfig-devel.i686
|
||||
install fontconfig-devel.x86_64
|
||||
install fontconfig.i686
|
||||
|
||||
@@ -29,7 +29,6 @@ parts:
|
||||
source: source
|
||||
stage-packages:
|
||||
- libxt6
|
||||
- libdbus-glib-1-2
|
||||
- libasound2
|
||||
- libpulse0
|
||||
- libgl1-mesa-dri
|
||||
|
||||
@@ -44,7 +44,6 @@ apt_packages+=('libasound2-plugins:i386')
|
||||
apt_packages+=('libcanberra-pulse')
|
||||
apt_packages+=('libcurl4-openssl-dev')
|
||||
apt_packages+=('libdbus-1-dev')
|
||||
apt_packages+=('libdbus-glib-1-dev')
|
||||
apt_packages+=('libdrm-intel1:i386')
|
||||
apt_packages+=('libdrm-nouveau1a:i386')
|
||||
apt_packages+=('libdrm-radeon1:i386')
|
||||
|
||||
@@ -37,7 +37,6 @@ apt_packages+=('libasound2-dev')
|
||||
apt_packages+=('libcanberra-pulse')
|
||||
apt_packages+=('libcurl4-openssl-dev')
|
||||
apt_packages+=('libdbus-1-dev')
|
||||
apt_packages+=('libdbus-glib-1-dev')
|
||||
apt_packages+=('libgconf2-dev')
|
||||
apt_packages+=('libgstreamer-plugins-base0.10-dev')
|
||||
apt_packages+=('libgstreamer0.10-dev')
|
||||
|
||||
@@ -134,7 +134,7 @@ config = {
|
||||
# -devel packages dependencies. So manually install the dependencies
|
||||
# of the above packages.
|
||||
'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686',
|
||||
'fontconfig-devel.i686', 'glib2-devel.i686',
|
||||
'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686',
|
||||
'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686',
|
||||
|
||||
@@ -90,7 +90,7 @@ config = {
|
||||
# -devel packages dependencies. So manually install the dependencies
|
||||
# of the above packages.
|
||||
'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686',
|
||||
'fontconfig-devel.i686', 'glib2-devel.i686',
|
||||
'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686',
|
||||
'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686',
|
||||
|
||||
@@ -96,7 +96,7 @@ config = {
|
||||
# -devel packages dependencies. So manually install the dependencies
|
||||
# of the above packages.
|
||||
'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686',
|
||||
'fontconfig-devel.i686', 'glib2-devel.i686',
|
||||
'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686',
|
||||
'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686',
|
||||
|
||||
@@ -58,7 +58,7 @@ config = {
|
||||
"gmp-devel", "nspr", "nspr-devel",
|
||||
|
||||
# For building the browser
|
||||
"dbus-devel", "dbus-glib-devel", "hal-devel",
|
||||
"dbus-devel", "hal-devel",
|
||||
"libICE-devel", "libIDL-devel",
|
||||
|
||||
# For mach resource-usage
|
||||
|
||||
@@ -92,7 +92,7 @@ config = {
|
||||
# -devel packages dependencies. So manually install the dependencies
|
||||
# of the above packages.
|
||||
'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686',
|
||||
'check-devel.i686', 'dbus-devel.i686',
|
||||
'fontconfig-devel.i686', 'glib2-devel.i686',
|
||||
'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686',
|
||||
'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686',
|
||||
|
||||
@@ -218,7 +218,7 @@ if CONFIG['MOZ_SNDIO']:
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ENABLE_DBUS']:
|
||||
OS_LIBS += CONFIG['MOZ_DBUS_GLIB_LIBS']
|
||||
OS_LIBS += CONFIG['MOZ_DBUS_LIBS']
|
||||
|
||||
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
|
||||
|
||||
@@ -134,7 +134,6 @@ if CONFIG['MOZ_ENABLE_XREMOTE']:
|
||||
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
||||
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
|
||||
CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
|
||||
|
||||
@@ -122,4 +122,3 @@ if CONFIG['MOZ_ENABLE_DBUS']:
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
||||
@@ -3020,6 +3020,7 @@ nsLocalFile::IsExecutable(bool* aResult)
|
||||
"air", // Adobe AIR installer
|
||||
"app", // executable application
|
||||
"application", // from bug 348763
|
||||
"appref-ms", // ClickOnce link
|
||||
"appx",
|
||||
"appxbundle",
|
||||
"asp",
|
||||
@@ -3080,6 +3081,7 @@ nsLocalFile::IsExecutable(bool* aResult)
|
||||
"scf", // Windows explorer command
|
||||
"scr",
|
||||
"sct",
|
||||
"search-ms", // Windows Saved Search
|
||||
"settingcontent-ms",
|
||||
"shb",
|
||||
"shs",
|
||||
|
||||
Reference in New Issue
Block a user