linux-kselftest-4.10-rc1-update
This update consists of: -- New tests to exercise the Sync Kernel Infrastructure. These tests are part of a battery of Android libsync tests and are re-written to test the new sync user-space interfaces from Emilio López, and Gustavo Padovan. -- Test to run hw-independent mock tests for i915.ko from Chris Wilson -- A new gpio test case from Bamvor Jian Zhang -- Missing gitignore additions -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJYUv0yAAoJEAsCRMQNDUMcNVQP/0JaO+AaA0GyrxtBlaj4R/sJ VI4wQGPIqPGk+DtyjoZ4zkGPZzdY7U05wgJeUrm0/K263XaijjneCvfskCG/2R4d 1rO0sAOXSsgpDnQ1Nt2hDAV42zSwecFWFl4odfe1oHznME+fKGg7tXHX74/R8FZp eMhg0UYME5Dpq4dC3s3NxDYcieHVq9e8v2A5eJx5PjTbcrnztkKzdBiNWUWaW4Jt qyUmTVBA2M/vTDyJWCzfTBFadVpYBycewIZdDpQN682VFT6d+mvN/hP6pRYGqNwd FDhM1asdhQiJXEmNd7Muufz3CZ5FlzV3VW+u+eZkeEwInw4uwtajXvqM8+5K4YyE yKcnCXyFjsmnJtsEba6Gf8S35Dbzcx7j3nJRkqk+ULcGKSUHR2GnWtltZUKtKsqp /aB8M1H+xoLKdzDnMADNZG/6YMhGq/QOJn1qocn2HmDUSawjUMriCm2ylo09YQwH Ud0WVSTZZD+jWRLAB6nLXOREXLincZ0e7z2wfV/SHQ1d7MaS9lidxSRbwaRLd9+f iZ9WS9xkW8axxpe3vmgHdIxxrhy7LLJe+4b/iDo/iMC9waFv6qXcYh7l5/bEXoIz 0D1eB4L5mBHF032tSatjxy1ewy9uiU5M9STmZVdL6Jla7qsxHQEc0x5cr2evpQ4/ tjautkTKCbWocEl/KLPt =qjL9 -----END PGP SIGNATURE----- Merge tag 'linux-kselftest-4.10-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest Pull kselftest updates from Shuah Khan: "This update consists of: - new tests to exercise the Sync Kernel Infrastructure. These tests are part of a battery of Android libsync tests and are re-written to test the new sync user-space interfaces from Emilio López, and Gustavo Padovan. - test to run hw-independent mock tests for i915.ko from Chris Wilson - a new gpio test case from Bamvor Jian Zhang - missing gitignore additions" * tag 'linux-kselftest-4.10-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: selftest/gpio: add gpio test case selftest: sync: improve assert() failure message kselftests: Exercise hw-independent mock tests for i915.ko selftests: add missing gitignore files/dirs selftests: add missing set-tz to timers .gitignore selftest: sync: stress test for merges selftest: sync: stress consumer/producer test selftest: sync: stress test for parallelism selftest: sync: wait tests for sw_sync framework selftest: sync: merge tests for sw_sync framework selftest: sync: fence tests for sw_sync framework selftest: sync: basic tests for sw_sync framework
This commit is contained in:
commit
09dee2a608
|
@ -0,0 +1 @@
|
|||
kselftest
|
|
@ -7,6 +7,7 @@ TARGETS += exec
|
|||
TARGETS += firmware
|
||||
TARGETS += ftrace
|
||||
TARGETS += futex
|
||||
TARGETS += gpio
|
||||
TARGETS += ipc
|
||||
TARGETS += kcmp
|
||||
TARGETS += lib
|
||||
|
@ -24,6 +25,7 @@ TARGETS += seccomp
|
|||
TARGETS += sigaltstack
|
||||
TARGETS += size
|
||||
TARGETS += static_keys
|
||||
TARGETS += sync
|
||||
TARGETS += sysctl
|
||||
ifneq (1, $(quicktest))
|
||||
TARGETS += timers
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Runs hardware independent tests for i915 (drivers/gpu/drm/i915)
|
||||
|
||||
if ! /sbin/modprobe -q -r i915; then
|
||||
echo "drivers/gpu/i915: [SKIP]"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
if /sbin/modprobe -q i915 mock_selftests=-1; then
|
||||
echo "drivers/gpu/i915: ok"
|
||||
else
|
||||
echo "drivers/gpu/i915: [FAIL]"
|
||||
exit 1
|
||||
fi
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
TEST_PROGS := gpio-mockup.sh
|
||||
TEST_FILES := gpio-mockup-sysfs.sh $(BINARIES)
|
||||
BINARIES := gpio-mockup-chardev
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
all: $(BINARIES)
|
||||
|
||||
clean:
|
||||
$(RM) $(BINARIES)
|
||||
|
||||
CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/
|
||||
LDLIBS += -lmount -I/usr/include/libmount
|
||||
|
||||
$(BINARIES): ../../../gpio/gpio-utils.o ../../../../usr/include/linux/gpio.h
|
||||
|
||||
../../../gpio/gpio-utils.o:
|
||||
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C ../../../gpio
|
||||
|
||||
../../../../usr/include/linux/gpio.h:
|
||||
make -C ../../../.. headers_install INSTALL_HDR_PATH=$(shell pwd)/../../../../usr/
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* GPIO chardev test helper
|
||||
*
|
||||
* Copyright (C) 2016 Bamvor Jian Zhang
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <libmount.h>
|
||||
#include <err.h>
|
||||
#include <dirent.h>
|
||||
#include <linux/gpio.h>
|
||||
#include "../../../gpio/gpio-utils.h"
|
||||
|
||||
#define CONSUMER "gpio-selftest"
|
||||
#define GC_NUM 10
|
||||
enum direction {
|
||||
OUT,
|
||||
IN
|
||||
};
|
||||
|
||||
static int get_debugfs(char **path)
|
||||
{
|
||||
struct libmnt_context *cxt;
|
||||
struct libmnt_table *tb;
|
||||
struct libmnt_iter *itr = NULL;
|
||||
struct libmnt_fs *fs;
|
||||
int found = 0;
|
||||
|
||||
cxt = mnt_new_context();
|
||||
if (!cxt)
|
||||
err(EXIT_FAILURE, "libmount context allocation failed");
|
||||
|
||||
itr = mnt_new_iter(MNT_ITER_FORWARD);
|
||||
if (!itr)
|
||||
err(EXIT_FAILURE, "failed to initialize libmount iterator");
|
||||
|
||||
if (mnt_context_get_mtab(cxt, &tb))
|
||||
err(EXIT_FAILURE, "failed to read mtab");
|
||||
|
||||
while (mnt_table_next_fs(tb, itr, &fs) == 0) {
|
||||
const char *type = mnt_fs_get_fstype(fs);
|
||||
|
||||
if (!strcmp(type, "debugfs")) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
|
||||
|
||||
mnt_free_iter(itr);
|
||||
mnt_free_context(cxt);
|
||||
|
||||
if (!found)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_debugfs_get(const char *consumer, int *dir, int *value)
|
||||
{
|
||||
char *debugfs;
|
||||
FILE *f;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
char *cur;
|
||||
int found = 0;
|
||||
|
||||
if (get_debugfs(&debugfs) != 0)
|
||||
err(EXIT_FAILURE, "debugfs is not mounted");
|
||||
|
||||
f = fopen(debugfs, "r");
|
||||
if (!f)
|
||||
err(EXIT_FAILURE, "read from gpio debugfs failed");
|
||||
|
||||
/*
|
||||
* gpio-2 ( |gpio-selftest ) in lo
|
||||
*/
|
||||
while (getline(&line, &len, f) != -1) {
|
||||
cur = strstr(line, consumer);
|
||||
if (cur == NULL)
|
||||
continue;
|
||||
|
||||
cur = strchr(line, ')');
|
||||
if (!cur)
|
||||
continue;
|
||||
|
||||
cur += 2;
|
||||
if (!strncmp(cur, "out", 3)) {
|
||||
*dir = OUT;
|
||||
cur += 4;
|
||||
} else if (!strncmp(cur, "in", 2)) {
|
||||
*dir = IN;
|
||||
cur += 4;
|
||||
}
|
||||
|
||||
if (!strncmp(cur, "hi", 2))
|
||||
*value = 1;
|
||||
else if (!strncmp(cur, "lo", 2))
|
||||
*value = 0;
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
free(debugfs);
|
||||
fclose(f);
|
||||
free(line);
|
||||
|
||||
if (!found)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct gpiochip_info *list_gpiochip(const char *gpiochip_name, int *ret)
|
||||
{
|
||||
struct gpiochip_info *cinfo;
|
||||
struct gpiochip_info *current;
|
||||
const struct dirent *ent;
|
||||
DIR *dp;
|
||||
char *chrdev_name;
|
||||
int fd;
|
||||
int i = 0;
|
||||
|
||||
cinfo = calloc(sizeof(struct gpiochip_info) * 4, GC_NUM + 1);
|
||||
if (!cinfo)
|
||||
err(EXIT_FAILURE, "gpiochip_info allocation failed");
|
||||
|
||||
current = cinfo;
|
||||
dp = opendir("/dev");
|
||||
if (!dp) {
|
||||
*ret = -errno;
|
||||
goto error_out;
|
||||
} else {
|
||||
*ret = 0;
|
||||
}
|
||||
|
||||
while (ent = readdir(dp), ent) {
|
||||
if (check_prefix(ent->d_name, "gpiochip")) {
|
||||
*ret = asprintf(&chrdev_name, "/dev/%s", ent->d_name);
|
||||
if (*ret < 0)
|
||||
goto error_out;
|
||||
|
||||
fd = open(chrdev_name, 0);
|
||||
if (fd == -1) {
|
||||
*ret = -errno;
|
||||
fprintf(stderr, "Failed to open %s\n",
|
||||
chrdev_name);
|
||||
goto error_close_dir;
|
||||
}
|
||||
*ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, current);
|
||||
if (*ret == -1) {
|
||||
perror("Failed to issue CHIPINFO IOCTL\n");
|
||||
goto error_close_dir;
|
||||
}
|
||||
close(fd);
|
||||
if (strcmp(current->label, gpiochip_name) == 0
|
||||
|| check_prefix(current->label, gpiochip_name)) {
|
||||
*ret = 0;
|
||||
current++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!*ret && i == 0) || *ret < 0) {
|
||||
free(cinfo);
|
||||
cinfo = NULL;
|
||||
}
|
||||
if (!*ret && i > 0) {
|
||||
cinfo = realloc(cinfo, sizeof(struct gpiochip_info) * 4 * i);
|
||||
*ret = i;
|
||||
}
|
||||
|
||||
error_close_dir:
|
||||
closedir(dp);
|
||||
error_out:
|
||||
if (*ret < 0)
|
||||
err(EXIT_FAILURE, "list gpiochip failed: %s", strerror(*ret));
|
||||
|
||||
return cinfo;
|
||||
}
|
||||
|
||||
int gpio_pin_test(struct gpiochip_info *cinfo, int line, int flag, int value)
|
||||
{
|
||||
struct gpiohandle_data data;
|
||||
unsigned int lines[] = {line};
|
||||
int fd;
|
||||
int debugfs_dir = IN;
|
||||
int debugfs_value = 0;
|
||||
int ret;
|
||||
|
||||
data.values[0] = value;
|
||||
ret = gpiotools_request_linehandle(cinfo->name, lines, 1, flag, &data,
|
||||
CONSUMER);
|
||||
if (ret < 0)
|
||||
goto fail_out;
|
||||
else
|
||||
fd = ret;
|
||||
|
||||
ret = gpio_debugfs_get(CONSUMER, &debugfs_dir, &debugfs_value);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto fail_out;
|
||||
}
|
||||
if (flag & GPIOHANDLE_REQUEST_INPUT) {
|
||||
if (debugfs_dir != IN) {
|
||||
errno = -EINVAL;
|
||||
ret = -errno;
|
||||
}
|
||||
} else if (flag & GPIOHANDLE_REQUEST_OUTPUT) {
|
||||
if (flag & GPIOHANDLE_REQUEST_ACTIVE_LOW)
|
||||
debugfs_value = !debugfs_value;
|
||||
|
||||
if (!(debugfs_dir == OUT && value == debugfs_value))
|
||||
errno = -EINVAL;
|
||||
ret = -errno;
|
||||
|
||||
}
|
||||
gpiotools_release_linehandle(fd);
|
||||
|
||||
fail_out:
|
||||
if (ret)
|
||||
err(EXIT_FAILURE, "gpio<%s> line<%d> test flag<0x%x> value<%d>",
|
||||
cinfo->name, line, flag, value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gpio_pin_tests(struct gpiochip_info *cinfo, unsigned int line)
|
||||
{
|
||||
printf("line<%d>", line);
|
||||
gpio_pin_test(cinfo, line, GPIOHANDLE_REQUEST_OUTPUT, 0);
|
||||
printf(".");
|
||||
gpio_pin_test(cinfo, line, GPIOHANDLE_REQUEST_OUTPUT, 1);
|
||||
printf(".");
|
||||
gpio_pin_test(cinfo, line,
|
||||
GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW,
|
||||
0);
|
||||
printf(".");
|
||||
gpio_pin_test(cinfo, line,
|
||||
GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW,
|
||||
1);
|
||||
printf(".");
|
||||
gpio_pin_test(cinfo, line, GPIOHANDLE_REQUEST_INPUT, 0);
|
||||
printf(".");
|
||||
}
|
||||
|
||||
/*
|
||||
* ./gpio-mockup-chardev gpio_chip_name_prefix is_valid_gpio_chip
|
||||
* Return 0 if successful or exit with EXIT_FAILURE if test failed.
|
||||
* gpio_chip_name_prefix: The prefix of gpiochip you want to test. E.g.
|
||||
* gpio-mockup
|
||||
* is_valid_gpio_chip: Whether the gpio_chip is valid. 1 means valid,
|
||||
* 0 means invalid which could not be found by
|
||||
* list_gpiochip.
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *prefix;
|
||||
int valid;
|
||||
struct gpiochip_info *cinfo;
|
||||
struct gpiochip_info *current;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s prefix is_valid", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
prefix = argv[1];
|
||||
valid = strcmp(argv[2], "true") == 0 ? 1 : 0;
|
||||
|
||||
printf("Test gpiochip %s: ", prefix);
|
||||
cinfo = list_gpiochip(prefix, &ret);
|
||||
if (!cinfo) {
|
||||
if (!valid && ret == 0) {
|
||||
printf("Invalid test successful\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else if (cinfo && !valid) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
current = cinfo;
|
||||
for (i = 0; i < ret; i++) {
|
||||
gpio_pin_tests(current, 0);
|
||||
gpio_pin_tests(current, current->lines - 1);
|
||||
gpio_pin_tests(current, random() % current->lines);
|
||||
current++;
|
||||
}
|
||||
ret = 0;
|
||||
printf("successful\n");
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
fprintf(stderr, "gpio<%s> test failed\n", prefix);
|
||||
|
||||
if (cinfo)
|
||||
free(cinfo);
|
||||
|
||||
if (ret)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
|
||||
is_consistent()
|
||||
{
|
||||
val=
|
||||
|
||||
active_low_sysfs=`cat $GPIO_SYSFS/gpio$nr/active_low`
|
||||
val_sysfs=`cat $GPIO_SYSFS/gpio$nr/value`
|
||||
dir_sysfs=`cat $GPIO_SYSFS/gpio$nr/direction`
|
||||
|
||||
gpio_this_debugfs=`cat $GPIO_DEBUGFS |grep "gpio-$nr" | sed "s/(.*)//g"`
|
||||
dir_debugfs=`echo $gpio_this_debugfs | awk '{print $2}'`
|
||||
val_debugfs=`echo $gpio_this_debugfs | awk '{print $3}'`
|
||||
if [ $val_debugfs = "lo" ]; then
|
||||
val=0
|
||||
elif [ $val_debugfs = "hi" ]; then
|
||||
val=1
|
||||
fi
|
||||
|
||||
if [ $active_low_sysfs = "1" ]; then
|
||||
if [ $val = "0" ]; then
|
||||
val="1"
|
||||
else
|
||||
val="0"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $val_sysfs = $val ] && [ $dir_sysfs = $dir_debugfs ]; then
|
||||
echo -n "."
|
||||
else
|
||||
echo "test fail, exit"
|
||||
die
|
||||
fi
|
||||
}
|
||||
|
||||
test_pin_logic()
|
||||
{
|
||||
nr=$1
|
||||
direction=$2
|
||||
active_low=$3
|
||||
value=$4
|
||||
|
||||
echo $direction > $GPIO_SYSFS/gpio$nr/direction
|
||||
echo $active_low > $GPIO_SYSFS/gpio$nr/active_low
|
||||
if [ $direction = "out" ]; then
|
||||
echo $value > $GPIO_SYSFS/gpio$nr/value
|
||||
fi
|
||||
is_consistent $nr
|
||||
}
|
||||
|
||||
test_one_pin()
|
||||
{
|
||||
nr=$1
|
||||
|
||||
echo -n "test pin<$nr>"
|
||||
|
||||
echo $nr > $GPIO_SYSFS/export 2>/dev/null
|
||||
|
||||
if [ X$? != X0 ]; then
|
||||
echo "test GPIO pin $nr failed"
|
||||
die
|
||||
fi
|
||||
|
||||
#"Checking if the sysfs is consistent with debugfs: "
|
||||
is_consistent $nr
|
||||
|
||||
#"Checking the logic of active_low: "
|
||||
test_pin_logic $nr out 1 1
|
||||
test_pin_logic $nr out 1 0
|
||||
test_pin_logic $nr out 0 1
|
||||
test_pin_logic $nr out 0 0
|
||||
|
||||
#"Checking the logic of direction: "
|
||||
test_pin_logic $nr in 1 1
|
||||
test_pin_logic $nr out 1 0
|
||||
test_pin_logic $nr low 0 1
|
||||
test_pin_logic $nr high 0 0
|
||||
|
||||
echo $nr > $GPIO_SYSFS/unexport
|
||||
|
||||
echo "successful"
|
||||
}
|
||||
|
||||
test_one_pin_fail()
|
||||
{
|
||||
nr=$1
|
||||
|
||||
echo $nr > $GPIO_SYSFS/export 2>/dev/null
|
||||
|
||||
if [ X$? != X0 ]; then
|
||||
echo "test invalid pin $nr successful"
|
||||
else
|
||||
echo "test invalid pin $nr failed"
|
||||
echo $nr > $GPIO_SYSFS/unexport 2>/dev/null
|
||||
die
|
||||
fi
|
||||
}
|
||||
|
||||
list_chip()
|
||||
{
|
||||
echo `ls -d $GPIO_DRV_SYSFS/gpiochip* 2>/dev/null`
|
||||
}
|
||||
|
||||
test_chip()
|
||||
{
|
||||
chip=$1
|
||||
name=`basename $chip`
|
||||
base=`cat $chip/base`
|
||||
ngpio=`cat $chip/ngpio`
|
||||
printf "%-10s %-5s %-5s\n" $name $base $ngpio
|
||||
if [ $ngpio = "0" ]; then
|
||||
echo "number of gpio is zero is not allowed".
|
||||
fi
|
||||
test_one_pin $base
|
||||
test_one_pin $(($base + $ngpio - 1))
|
||||
test_one_pin $((( RANDOM % $ngpio ) + $base ))
|
||||
}
|
||||
|
||||
test_chips_sysfs()
|
||||
{
|
||||
gpiochip=`list_chip $module`
|
||||
if [ X"$gpiochip" = X ]; then
|
||||
if [ X"$valid" = Xfalse ]; then
|
||||
echo "successful"
|
||||
else
|
||||
echo "fail"
|
||||
die
|
||||
fi
|
||||
else
|
||||
for chip in $gpiochip; do
|
||||
test_chip $chip
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
#!/bin/bash
|
||||
|
||||
#exit status
|
||||
#1: run as non-root user
|
||||
#2: sysfs/debugfs not mount
|
||||
#3: insert module fail when gpio-mockup is a module.
|
||||
#4: other reason.
|
||||
|
||||
SYSFS=
|
||||
GPIO_SYSFS=
|
||||
GPIO_DRV_SYSFS=
|
||||
DEBUGFS=
|
||||
GPIO_DEBUGFS=
|
||||
dev_type=
|
||||
module=
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "Usage:"
|
||||
echo "$0 [-f] [-m name] [-t type]"
|
||||
echo "-f: full test. It maybe conflict with existence gpio device."
|
||||
echo "-m: module name, default name is gpio-mockup. It could also test"
|
||||
echo " other gpio device."
|
||||
echo "-t: interface type: chardev(char device) and sysfs(being"
|
||||
echo " deprecated). The first one is default"
|
||||
echo ""
|
||||
echo "$0 -h"
|
||||
echo "This usage"
|
||||
}
|
||||
|
||||
prerequisite()
|
||||
{
|
||||
msg="skip all tests:"
|
||||
if [ $UID != 0 ]; then
|
||||
echo $msg must be run as root >&2
|
||||
exit 1
|
||||
fi
|
||||
SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
|
||||
if [ ! -d "$SYSFS" ]; then
|
||||
echo $msg sysfs is not mounted >&2
|
||||
exit 2
|
||||
fi
|
||||
GPIO_SYSFS=`echo $SYSFS/class/gpio`
|
||||
GPIO_DRV_SYSFS=`echo $SYSFS/devices/platform/$module/gpio`
|
||||
DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
|
||||
if [ ! -d "$DEBUGFS" ]; then
|
||||
echo $msg debugfs is not mounted >&2
|
||||
exit 2
|
||||
fi
|
||||
GPIO_DEBUGFS=`echo $DEBUGFS/gpio`
|
||||
source gpio-mockup-sysfs.sh
|
||||
}
|
||||
|
||||
try_insert_module()
|
||||
{
|
||||
if [ -d "$GPIO_DRV_SYSFS" ]; then
|
||||
echo "$GPIO_DRV_SYSFS exist. Skip insert module"
|
||||
else
|
||||
modprobe -q $module $1
|
||||
if [ X$? != X0 ]; then
|
||||
echo $msg insmod $module failed >&2
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
remove_module()
|
||||
{
|
||||
modprobe -r -q $module
|
||||
}
|
||||
|
||||
die()
|
||||
{
|
||||
remove_module
|
||||
exit 4
|
||||
}
|
||||
|
||||
test_chips()
|
||||
{
|
||||
if [ X$dev_type = Xsysfs ]; then
|
||||
echo "WARNING: sysfs ABI of gpio is going to deprecated."
|
||||
test_chips_sysfs $*
|
||||
else
|
||||
$BASE/gpio-mockup-chardev $*
|
||||
fi
|
||||
}
|
||||
|
||||
gpio_test()
|
||||
{
|
||||
param=$1
|
||||
valid=$2
|
||||
|
||||
if [ X"$param" = X ]; then
|
||||
die
|
||||
fi
|
||||
try_insert_module "gpio_mockup_ranges=$param"
|
||||
echo -n "GPIO $module test with ranges: <"
|
||||
echo "$param>: "
|
||||
printf "%-10s %s\n" $param
|
||||
test_chips $module $valid
|
||||
remove_module
|
||||
}
|
||||
|
||||
BASE=`dirname $0`
|
||||
|
||||
dev_type=
|
||||
TEMP=`getopt -o fhm:t: -n '$0' -- "$@"`
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "Parameter process failed, Terminating..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Note the quotes around `$TEMP': they are essential!
|
||||
eval set -- "$TEMP"
|
||||
|
||||
while true; do
|
||||
case $1 in
|
||||
-f)
|
||||
full_test=true
|
||||
shift
|
||||
;;
|
||||
-h)
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
-m)
|
||||
module=$2
|
||||
shift 2
|
||||
;;
|
||||
-t)
|
||||
dev_type=$2
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Internal error!"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ X"$module" = X ]; then
|
||||
module="gpio-mockup"
|
||||
fi
|
||||
|
||||
if [ X$dev_type != Xsysfs ]; then
|
||||
dev_type="chardev"
|
||||
fi
|
||||
|
||||
prerequisite
|
||||
|
||||
echo "1. Test dynamic allocation of gpio successful means insert gpiochip and"
|
||||
echo " manipulate gpio pin successful"
|
||||
gpio_test "-1,32" true
|
||||
gpio_test "-1,32,-1,32" true
|
||||
gpio_test "-1,32,-1,32,-1,32" true
|
||||
if [ X$full_test = Xtrue ]; then
|
||||
gpio_test "-1,32,32,64" true
|
||||
gpio_test "-1,32,40,64,-1,5" true
|
||||
gpio_test "-1,32,32,64,-1,32" true
|
||||
gpio_test "0,32,32,64,-1,32,-1,32" true
|
||||
gpio_test "-1,32,-1,32,0,32,32,64" true
|
||||
echo "2. Do basic test: successful means insert gpiochip and"
|
||||
echo " manipulate gpio pin successful"
|
||||
gpio_test "0,32" true
|
||||
gpio_test "0,32,32,64" true
|
||||
gpio_test "0,32,40,64,64,96" true
|
||||
fi
|
||||
echo "3. Error test: successful means insert gpiochip failed"
|
||||
echo "3.1 Test number of gpio overflow"
|
||||
#Currently: The max number of gpio(1024) is defined in arm architecture.
|
||||
gpio_test "-1,32,-1,1024" false
|
||||
if [ X$full_test = Xtrue ]; then
|
||||
echo "3.2 Test zero line of gpio"
|
||||
gpio_test "0,0" false
|
||||
echo "3.3 Test range overlap"
|
||||
echo "3.3.1 Test corner case"
|
||||
gpio_test "0,32,0,1" false
|
||||
gpio_test "0,32,32,64,32,40" false
|
||||
gpio_test "0,32,35,64,35,45" false
|
||||
gpio_test "0,32,31,32" false
|
||||
gpio_test "0,32,32,64,36,37" false
|
||||
gpio_test "0,32,35,64,34,36" false
|
||||
echo "3.3.2 Test inserting invalid second gpiochip"
|
||||
gpio_test "0,32,30,35" false
|
||||
gpio_test "0,32,1,5" false
|
||||
gpio_test "10,32,9,14" false
|
||||
gpio_test "10,32,30,35" false
|
||||
echo "3.3.3 Test others"
|
||||
gpio_test "0,32,40,56,39,45" false
|
||||
gpio_test "0,32,40,56,30,33" false
|
||||
gpio_test "0,32,40,56,30,41" false
|
||||
gpio_test "0,32,40,56,20,21" false
|
||||
fi
|
||||
|
||||
echo GPIO test PASS
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
owner
|
||||
pidns
|
|
@ -0,0 +1 @@
|
|||
sas
|
|
@ -0,0 +1 @@
|
|||
sync_test
|
|
@ -0,0 +1,24 @@
|
|||
CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
|
||||
CFLAGS += -I../../../../usr/include/
|
||||
LDFLAGS += -pthread
|
||||
|
||||
TEST_PROGS = sync_test
|
||||
|
||||
all: $(TEST_PROGS)
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
OBJS = sync_test.o sync.o
|
||||
|
||||
TESTS += sync_alloc.o
|
||||
TESTS += sync_fence.o
|
||||
TESTS += sync_merge.o
|
||||
TESTS += sync_wait.o
|
||||
TESTS += sync_stress_parallelism.o
|
||||
TESTS += sync_stress_consumer.o
|
||||
TESTS += sync_stress_merge.o
|
||||
|
||||
sync_test: $(OBJS) $(TESTS)
|
||||
|
||||
clean:
|
||||
$(RM) sync_test $(OBJS) $(TESTS)
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* sw_sync abstraction
|
||||
*
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2013 Google, Inc
|
||||
*
|
||||
* 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 SELFTESTS_SW_SYNC_H
|
||||
#define SELFTESTS_SW_SYNC_H
|
||||
|
||||
/*
|
||||
* sw_sync is mainly intended for testing and should not be compiled into
|
||||
* production kernels
|
||||
*/
|
||||
|
||||
int sw_sync_timeline_create(void);
|
||||
int sw_sync_timeline_is_valid(int fd);
|
||||
int sw_sync_timeline_inc(int fd, unsigned int count);
|
||||
void sw_sync_timeline_destroy(int fd);
|
||||
|
||||
int sw_sync_fence_create(int fd, const char *name, unsigned int value);
|
||||
int sw_sync_fence_is_valid(int fd);
|
||||
void sw_sync_fence_destroy(int fd);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* sync / sw_sync abstraction
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <poll.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sync.h"
|
||||
#include "sw_sync.h"
|
||||
|
||||
#include <linux/sync_file.h>
|
||||
|
||||
|
||||
/* SW_SYNC ioctls */
|
||||
struct sw_sync_create_fence_data {
|
||||
__u32 value;
|
||||
char name[32];
|
||||
__s32 fence;
|
||||
};
|
||||
|
||||
#define SW_SYNC_IOC_MAGIC 'W'
|
||||
#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
|
||||
struct sw_sync_create_fence_data)
|
||||
#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
|
||||
|
||||
|
||||
int sync_wait(int fd, int timeout)
|
||||
{
|
||||
struct pollfd fds;
|
||||
|
||||
fds.fd = fd;
|
||||
fds.events = POLLIN | POLLERR;
|
||||
|
||||
return poll(&fds, 1, timeout);
|
||||
}
|
||||
|
||||
int sync_merge(const char *name, int fd1, int fd2)
|
||||
{
|
||||
struct sync_merge_data data = {};
|
||||
int err;
|
||||
|
||||
data.fd2 = fd2;
|
||||
strncpy(data.name, name, sizeof(data.name) - 1);
|
||||
data.name[sizeof(data.name) - 1] = '\0';
|
||||
|
||||
err = ioctl(fd1, SYNC_IOC_MERGE, &data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return data.fence;
|
||||
}
|
||||
|
||||
static struct sync_file_info *sync_file_info(int fd)
|
||||
{
|
||||
struct sync_file_info *info;
|
||||
struct sync_fence_info *fence_info;
|
||||
int err, num_fences;
|
||||
|
||||
info = calloc(1, sizeof(*info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
|
||||
if (err < 0) {
|
||||
free(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
num_fences = info->num_fences;
|
||||
|
||||
if (num_fences) {
|
||||
info->flags = 0;
|
||||
info->num_fences = num_fences;
|
||||
|
||||
fence_info = calloc(num_fences, sizeof(*fence_info));
|
||||
if (!fence_info) {
|
||||
free(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->sync_fence_info = (uint64_t)fence_info;
|
||||
|
||||
err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
|
||||
if (err < 0) {
|
||||
free(fence_info);
|
||||
free(info);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void sync_file_info_free(struct sync_file_info *info)
|
||||
{
|
||||
free((void *)info->sync_fence_info);
|
||||
free(info);
|
||||
}
|
||||
|
||||
int sync_fence_size(int fd)
|
||||
{
|
||||
int count;
|
||||
struct sync_file_info *info = sync_file_info(fd);
|
||||
|
||||
if (!info)
|
||||
return 0;
|
||||
|
||||
count = info->num_fences;
|
||||
|
||||
sync_file_info_free(info);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int sync_fence_count_with_status(int fd, int status)
|
||||
{
|
||||
unsigned int i, count = 0;
|
||||
struct sync_fence_info *fence_info = NULL;
|
||||
struct sync_file_info *info = sync_file_info(fd);
|
||||
|
||||
if (!info)
|
||||
return -1;
|
||||
|
||||
fence_info = (struct sync_fence_info *)info->sync_fence_info;
|
||||
for (i = 0 ; i < info->num_fences ; i++) {
|
||||
if (fence_info[i].status == status)
|
||||
count++;
|
||||
}
|
||||
|
||||
sync_file_info_free(info);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int sw_sync_timeline_create(void)
|
||||
{
|
||||
return open("/sys/kernel/debug/sync/sw_sync", O_RDWR);
|
||||
}
|
||||
|
||||
int sw_sync_timeline_inc(int fd, unsigned int count)
|
||||
{
|
||||
__u32 arg = count;
|
||||
|
||||
return ioctl(fd, SW_SYNC_IOC_INC, &arg);
|
||||
}
|
||||
|
||||
int sw_sync_timeline_is_valid(int fd)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
status = fcntl(fd, F_GETFD, 0);
|
||||
return (status >= 0);
|
||||
}
|
||||
|
||||
void sw_sync_timeline_destroy(int fd)
|
||||
{
|
||||
if (sw_sync_timeline_is_valid(fd))
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int sw_sync_fence_create(int fd, const char *name, unsigned int value)
|
||||
{
|
||||
struct sw_sync_create_fence_data data = {};
|
||||
int err;
|
||||
|
||||
data.value = value;
|
||||
strncpy(data.name, name, sizeof(data.name) - 1);
|
||||
data.name[sizeof(data.name) - 1] = '\0';
|
||||
|
||||
err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return data.fence;
|
||||
}
|
||||
|
||||
int sw_sync_fence_is_valid(int fd)
|
||||
{
|
||||
/* Same code! */
|
||||
return sw_sync_timeline_is_valid(fd);
|
||||
}
|
||||
|
||||
void sw_sync_fence_destroy(int fd)
|
||||
{
|
||||
if (sw_sync_fence_is_valid(fd))
|
||||
close(fd);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* sync abstraction
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 SELFTESTS_SYNC_H
|
||||
#define SELFTESTS_SYNC_H
|
||||
|
||||
#define FENCE_STATUS_ERROR (-1)
|
||||
#define FENCE_STATUS_ACTIVE (0)
|
||||
#define FENCE_STATUS_SIGNALED (1)
|
||||
|
||||
int sync_wait(int fd, int timeout);
|
||||
int sync_merge(const char *name, int fd1, int fd2);
|
||||
int sync_fence_size(int fd);
|
||||
int sync_fence_count_with_status(int fd, int status);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* sync allocation tests
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 "sync.h"
|
||||
#include "sw_sync.h"
|
||||
#include "synctest.h"
|
||||
|
||||
int test_alloc_timeline(void)
|
||||
{
|
||||
int timeline, valid;
|
||||
|
||||
timeline = sw_sync_timeline_create();
|
||||
valid = sw_sync_timeline_is_valid(timeline);
|
||||
ASSERT(valid, "Failure allocating timeline\n");
|
||||
|
||||
sw_sync_timeline_destroy(timeline);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_alloc_fence(void)
|
||||
{
|
||||
int timeline, fence, valid;
|
||||
|
||||
timeline = sw_sync_timeline_create();
|
||||
valid = sw_sync_timeline_is_valid(timeline);
|
||||
ASSERT(valid, "Failure allocating timeline\n");
|
||||
|
||||
fence = sw_sync_fence_create(timeline, "allocFence", 1);
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure allocating fence\n");
|
||||
|
||||
sw_sync_fence_destroy(fence);
|
||||
sw_sync_timeline_destroy(timeline);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_alloc_fence_negative(void)
|
||||
{
|
||||
int fence, timeline;
|
||||
|
||||
timeline = sw_sync_timeline_create();
|
||||
ASSERT(timeline > 0, "Failure allocating timeline\n");
|
||||
|
||||
fence = sw_sync_fence_create(-1, "fence", 1);
|
||||
ASSERT(fence < 0, "Success allocating negative fence\n");
|
||||
|
||||
sw_sync_fence_destroy(fence);
|
||||
sw_sync_timeline_destroy(timeline);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* sync fence tests with one timeline
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 "sync.h"
|
||||
#include "sw_sync.h"
|
||||
#include "synctest.h"
|
||||
|
||||
int test_fence_one_timeline_wait(void)
|
||||
{
|
||||
int fence, valid, ret;
|
||||
int timeline = sw_sync_timeline_create();
|
||||
|
||||
valid = sw_sync_timeline_is_valid(timeline);
|
||||
ASSERT(valid, "Failure allocating timeline\n");
|
||||
|
||||
fence = sw_sync_fence_create(timeline, "allocFence", 5);
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure allocating fence\n");
|
||||
|
||||
/* Wait on fence until timeout */
|
||||
ret = sync_wait(fence, 0);
|
||||
ASSERT(ret == 0, "Failure waiting on fence until timeout\n");
|
||||
|
||||
/* Advance timeline from 0 -> 1 */
|
||||
ret = sw_sync_timeline_inc(timeline, 1);
|
||||
ASSERT(ret == 0, "Failure advancing timeline\n");
|
||||
|
||||
/* Wait on fence until timeout */
|
||||
ret = sync_wait(fence, 0);
|
||||
ASSERT(ret == 0, "Failure waiting on fence until timeout\n");
|
||||
|
||||
/* Signal the fence */
|
||||
ret = sw_sync_timeline_inc(timeline, 4);
|
||||
ASSERT(ret == 0, "Failure signaling the fence\n");
|
||||
|
||||
/* Wait successfully */
|
||||
ret = sync_wait(fence, 0);
|
||||
ASSERT(ret > 0, "Failure waiting on fence\n");
|
||||
|
||||
/* Go even further, and confirm wait still succeeds */
|
||||
ret = sw_sync_timeline_inc(timeline, 10);
|
||||
ASSERT(ret == 0, "Failure going further\n");
|
||||
ret = sync_wait(fence, 0);
|
||||
ASSERT(ret > 0, "Failure waiting ahead\n");
|
||||
|
||||
sw_sync_fence_destroy(fence);
|
||||
sw_sync_timeline_destroy(timeline);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_fence_one_timeline_merge(void)
|
||||
{
|
||||
int a, b, c, d, valid;
|
||||
int timeline = sw_sync_timeline_create();
|
||||
|
||||
/* create fence a,b,c and then merge them all into fence d */
|
||||
a = sw_sync_fence_create(timeline, "allocFence", 1);
|
||||
b = sw_sync_fence_create(timeline, "allocFence", 2);
|
||||
c = sw_sync_fence_create(timeline, "allocFence", 3);
|
||||
|
||||
valid = sw_sync_fence_is_valid(a) &&
|
||||
sw_sync_fence_is_valid(b) &&
|
||||
sw_sync_fence_is_valid(c);
|
||||
ASSERT(valid, "Failure allocating fences\n");
|
||||
|
||||
d = sync_merge("mergeFence", b, a);
|
||||
d = sync_merge("mergeFence", c, d);
|
||||
valid = sw_sync_fence_is_valid(d);
|
||||
ASSERT(valid, "Failure merging fences\n");
|
||||
|
||||
/* confirm all fences have one active point (even d) */
|
||||
ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
|
||||
"a has too many active fences!\n");
|
||||
ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
|
||||
"b has too many active fences!\n");
|
||||
ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
|
||||
"c has too many active fences!\n");
|
||||
ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
|
||||
"d has too many active fences!\n");
|
||||
|
||||
/* confirm that d is not signaled until the max of a,b,c */
|
||||
sw_sync_timeline_inc(timeline, 1);
|
||||
ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_SIGNALED) == 1,
|
||||
"a did not signal!\n");
|
||||
ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 1,
|
||||
"d signaled too early!\n");
|
||||
|
||||
sw_sync_timeline_inc(timeline, 1);
|
||||
ASSERT(sync_fence_count_with_status(b, FENCE_STATUS_SIGNALED) == 1,
|
||||
"b did not signal!\n");
|
||||
ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 1,
|
||||
"d signaled too early!\n");
|
||||
|
||||
sw_sync_timeline_inc(timeline, 1);
|
||||
ASSERT(sync_fence_count_with_status(c, FENCE_STATUS_SIGNALED) == 1,
|
||||
"c did not signal!\n");
|
||||
ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 0 &&
|
||||
sync_fence_count_with_status(d, FENCE_STATUS_SIGNALED) == 1,
|
||||
"d did not signal!\n");
|
||||
|
||||
sw_sync_fence_destroy(d);
|
||||
sw_sync_fence_destroy(c);
|
||||
sw_sync_fence_destroy(b);
|
||||
sw_sync_fence_destroy(a);
|
||||
sw_sync_timeline_destroy(timeline);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* sync fence merge tests
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 "sync.h"
|
||||
#include "sw_sync.h"
|
||||
#include "synctest.h"
|
||||
|
||||
int test_fence_merge_same_fence(void)
|
||||
{
|
||||
int fence, valid, merged;
|
||||
int timeline = sw_sync_timeline_create();
|
||||
|
||||
valid = sw_sync_timeline_is_valid(timeline);
|
||||
ASSERT(valid, "Failure allocating timeline\n");
|
||||
|
||||
fence = sw_sync_fence_create(timeline, "allocFence", 5);
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure allocating fence\n");
|
||||
|
||||
merged = sync_merge("mergeFence", fence, fence);
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure merging fence\n");
|
||||
|
||||
ASSERT(sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED) == 0,
|
||||
"fence signaled too early!\n");
|
||||
|
||||
sw_sync_timeline_inc(timeline, 5);
|
||||
ASSERT(sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED) == 1,
|
||||
"fence did not signal!\n");
|
||||
|
||||
sw_sync_fence_destroy(merged);
|
||||
sw_sync_fence_destroy(fence);
|
||||
sw_sync_timeline_destroy(timeline);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* sync stress test: producer/consumer
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 <pthread.h>
|
||||
|
||||
#include "sync.h"
|
||||
#include "sw_sync.h"
|
||||
#include "synctest.h"
|
||||
|
||||
/* IMPORTANT NOTE: if you see this test failing on your system, it may be
|
||||
* due to a shortage of file descriptors. Please ensure your system has
|
||||
* a sensible limit for this test to finish correctly.
|
||||
*/
|
||||
|
||||
/* Returns 1 on error, 0 on success */
|
||||
static int busy_wait_on_fence(int fence)
|
||||
{
|
||||
int error, active;
|
||||
|
||||
do {
|
||||
error = sync_fence_count_with_status(fence, FENCE_STATUS_ERROR);
|
||||
ASSERT(error == 0, "Error occurred on fence\n");
|
||||
active = sync_fence_count_with_status(fence,
|
||||
FENCE_STATUS_ACTIVE);
|
||||
} while (active);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct {
|
||||
int iterations;
|
||||
int threads;
|
||||
int counter;
|
||||
int consumer_timeline;
|
||||
int *producer_timelines;
|
||||
pthread_mutex_t lock;
|
||||
} test_data_mpsc;
|
||||
|
||||
static int mpsc_producer_thread(void *d)
|
||||
{
|
||||
int id = (long)d;
|
||||
int fence, valid, i;
|
||||
int *producer_timelines = test_data_mpsc.producer_timelines;
|
||||
int consumer_timeline = test_data_mpsc.consumer_timeline;
|
||||
int iterations = test_data_mpsc.iterations;
|
||||
|
||||
for (i = 0; i < iterations; i++) {
|
||||
fence = sw_sync_fence_create(consumer_timeline, "fence", i);
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure creating fence\n");
|
||||
|
||||
/*
|
||||
* Wait for the consumer to finish. Use alternate
|
||||
* means of waiting on the fence
|
||||
*/
|
||||
|
||||
if ((iterations + id) % 8 != 0) {
|
||||
ASSERT(sync_wait(fence, -1) > 0,
|
||||
"Failure waiting on fence\n");
|
||||
} else {
|
||||
ASSERT(busy_wait_on_fence(fence) == 0,
|
||||
"Failure waiting on fence\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Every producer increments the counter, the consumer
|
||||
* checks and erases it
|
||||
*/
|
||||
pthread_mutex_lock(&test_data_mpsc.lock);
|
||||
test_data_mpsc.counter++;
|
||||
pthread_mutex_unlock(&test_data_mpsc.lock);
|
||||
|
||||
ASSERT(sw_sync_timeline_inc(producer_timelines[id], 1) == 0,
|
||||
"Error advancing producer timeline\n");
|
||||
|
||||
sw_sync_fence_destroy(fence);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpcs_consumer_thread(void)
|
||||
{
|
||||
int fence, merged, tmp, valid, it, i;
|
||||
int *producer_timelines = test_data_mpsc.producer_timelines;
|
||||
int consumer_timeline = test_data_mpsc.consumer_timeline;
|
||||
int iterations = test_data_mpsc.iterations;
|
||||
int n = test_data_mpsc.threads;
|
||||
|
||||
for (it = 1; it <= iterations; it++) {
|
||||
fence = sw_sync_fence_create(producer_timelines[0], "name", it);
|
||||
for (i = 1; i < n; i++) {
|
||||
tmp = sw_sync_fence_create(producer_timelines[i],
|
||||
"name", it);
|
||||
merged = sync_merge("name", tmp, fence);
|
||||
sw_sync_fence_destroy(tmp);
|
||||
sw_sync_fence_destroy(fence);
|
||||
fence = merged;
|
||||
}
|
||||
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure merging fences\n");
|
||||
|
||||
/*
|
||||
* Make sure we see an increment from every producer thread.
|
||||
* Vary the means by which we wait.
|
||||
*/
|
||||
if (iterations % 8 != 0) {
|
||||
ASSERT(sync_wait(fence, -1) > 0,
|
||||
"Producers did not increment as expected\n");
|
||||
} else {
|
||||
ASSERT(busy_wait_on_fence(fence) == 0,
|
||||
"Producers did not increment as expected\n");
|
||||
}
|
||||
|
||||
ASSERT(test_data_mpsc.counter == n * it,
|
||||
"Counter value mismatch!\n");
|
||||
|
||||
/* Release the producer threads */
|
||||
ASSERT(sw_sync_timeline_inc(consumer_timeline, 1) == 0,
|
||||
"Failure releasing producer threads\n");
|
||||
|
||||
sw_sync_fence_destroy(fence);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_consumer_stress_multi_producer_single_consumer(void)
|
||||
{
|
||||
int iterations = 1 << 12;
|
||||
int n = 5;
|
||||
long i, ret;
|
||||
int producer_timelines[n];
|
||||
int consumer_timeline;
|
||||
pthread_t threads[n];
|
||||
|
||||
consumer_timeline = sw_sync_timeline_create();
|
||||
for (i = 0; i < n; i++)
|
||||
producer_timelines[i] = sw_sync_timeline_create();
|
||||
|
||||
test_data_mpsc.producer_timelines = producer_timelines;
|
||||
test_data_mpsc.consumer_timeline = consumer_timeline;
|
||||
test_data_mpsc.iterations = iterations;
|
||||
test_data_mpsc.threads = n;
|
||||
test_data_mpsc.counter = 0;
|
||||
pthread_mutex_init(&test_data_mpsc.lock, NULL);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
pthread_create(&threads[i], NULL, (void * (*)(void *))
|
||||
mpsc_producer_thread, (void *)i);
|
||||
}
|
||||
|
||||
/* Consumer thread runs here */
|
||||
ret = mpcs_consumer_thread();
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* sync stress test: merging
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "sync.h"
|
||||
#include "sw_sync.h"
|
||||
#include "synctest.h"
|
||||
|
||||
int test_merge_stress_random_merge(void)
|
||||
{
|
||||
int i, size, ret;
|
||||
int timeline_count = 32;
|
||||
int merge_count = 1024 * 32;
|
||||
int timelines[timeline_count];
|
||||
int fence_map[timeline_count];
|
||||
int fence, tmpfence, merged, valid;
|
||||
int timeline, timeline_offset, sync_point;
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
for (i = 0; i < timeline_count; i++)
|
||||
timelines[i] = sw_sync_timeline_create();
|
||||
|
||||
fence = sw_sync_fence_create(timelines[0], "fence", 0);
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure creating fence\n");
|
||||
|
||||
memset(fence_map, -1, sizeof(fence_map));
|
||||
fence_map[0] = 0;
|
||||
|
||||
/*
|
||||
* Randomly create sync_points out of a fixed set of timelines,
|
||||
* and merge them together
|
||||
*/
|
||||
for (i = 0; i < merge_count; i++) {
|
||||
/* Generate sync_point. */
|
||||
timeline_offset = rand() % timeline_count;
|
||||
timeline = timelines[timeline_offset];
|
||||
sync_point = rand();
|
||||
|
||||
/* Keep track of the latest sync_point in each timeline. */
|
||||
if (fence_map[timeline_offset] == -1)
|
||||
fence_map[timeline_offset] = sync_point;
|
||||
else if (fence_map[timeline_offset] < sync_point)
|
||||
fence_map[timeline_offset] = sync_point;
|
||||
|
||||
/* Merge */
|
||||
tmpfence = sw_sync_fence_create(timeline, "fence", sync_point);
|
||||
merged = sync_merge("merge", tmpfence, fence);
|
||||
sw_sync_fence_destroy(tmpfence);
|
||||
sw_sync_fence_destroy(fence);
|
||||
fence = merged;
|
||||
|
||||
valid = sw_sync_fence_is_valid(merged);
|
||||
ASSERT(valid, "Failure creating fence i\n");
|
||||
}
|
||||
|
||||
size = 0;
|
||||
for (i = 0; i < timeline_count; i++)
|
||||
if (fence_map[i] != -1)
|
||||
size++;
|
||||
|
||||
/* Confirm our map matches the fence. */
|
||||
ASSERT(sync_fence_size(fence) == size,
|
||||
"Quantity of elements not matching\n");
|
||||
|
||||
/* Trigger the merged fence */
|
||||
for (i = 0; i < timeline_count; i++) {
|
||||
if (fence_map[i] != -1) {
|
||||
ret = sync_wait(fence, 0);
|
||||
ASSERT(ret == 0,
|
||||
"Failure waiting on fence until timeout\n");
|
||||
/* Increment the timeline to the last sync_point */
|
||||
sw_sync_timeline_inc(timelines[i], fence_map[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the fence is triggered. */
|
||||
ret = sync_wait(fence, 0);
|
||||
ASSERT(ret > 0, "Failure triggering fence\n");
|
||||
|
||||
sw_sync_fence_destroy(fence);
|
||||
|
||||
for (i = 0; i < timeline_count; i++)
|
||||
sw_sync_timeline_destroy(timelines[i]);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* sync stress test: parallelism
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 <pthread.h>
|
||||
|
||||
#include "sync.h"
|
||||
#include "sw_sync.h"
|
||||
#include "synctest.h"
|
||||
|
||||
static struct {
|
||||
int iterations;
|
||||
int timeline;
|
||||
int counter;
|
||||
} test_data_two_threads;
|
||||
|
||||
static int test_stress_two_threads_shared_timeline_thread(void *d)
|
||||
{
|
||||
int thread_id = (long)d;
|
||||
int timeline = test_data_two_threads.timeline;
|
||||
int iterations = test_data_two_threads.iterations;
|
||||
int fence, valid, ret, i;
|
||||
|
||||
for (i = 0; i < iterations; i++) {
|
||||
fence = sw_sync_fence_create(timeline, "fence",
|
||||
i * 2 + thread_id);
|
||||
valid = sw_sync_fence_is_valid(fence);
|
||||
ASSERT(valid, "Failure allocating fence\n");
|
||||
|
||||
/* Wait on the prior thread to complete */
|
||||
ret = sync_wait(fence, -1);
|
||||
ASSERT(ret > 0, "Problem occurred on prior thread\n");
|
||||
|
||||
/*
|
||||
* Confirm the previous thread's writes are visible
|
||||
* and then increment
|
||||
*/
|
||||
ASSERT(test_data_two_threads.counter == i * 2 + thread_id,
|
||||
"Counter got damaged!\n");
|
||||
test_data_two_threads.counter++;
|
||||
|
||||
/* Kick off the other thread */
|
||||
ret = sw_sync_timeline_inc(timeline, 1);
|
||||
ASSERT(ret == 0, "Advancing timeline failed\n");
|
||||
|
||||
sw_sync_fence_destroy(fence);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_stress_two_threads_shared_timeline(void)
|
||||
{
|
||||
pthread_t a, b;
|
||||
int valid;
|
||||
int timeline = sw_sync_timeline_create();
|
||||
|
||||
valid = sw_sync_timeline_is_valid(timeline);
|
||||
ASSERT(valid, "Failure allocating timeline\n");
|
||||
|
||||
test_data_two_threads.iterations = 1 << 16;
|
||||
test_data_two_threads.counter = 0;
|
||||
test_data_two_threads.timeline = timeline;
|
||||
|
||||
/*
|
||||
* Use a single timeline to synchronize two threads
|
||||
* hammmering on the same counter.
|
||||
*/
|
||||
|
||||
pthread_create(&a, NULL, (void *(*)(void *))
|
||||
test_stress_two_threads_shared_timeline_thread,
|
||||
(void *)0);
|
||||
pthread_create(&b, NULL, (void *(*)(void *))
|
||||
test_stress_two_threads_shared_timeline_thread,
|
||||
(void *)1);
|
||||
|
||||
pthread_join(a, NULL);
|
||||
pthread_join(b, NULL);
|
||||
|
||||
/* make sure the threads did not trample on one another */
|
||||
ASSERT(test_data_two_threads.counter ==
|
||||
test_data_two_threads.iterations * 2,
|
||||
"Counter has unexpected value\n");
|
||||
|
||||
sw_sync_timeline_destroy(timeline);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* sync test runner
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "synctest.h"
|
||||
|
||||
static int run_test(int (*test)(void), char *name)
|
||||
{
|
||||
int result;
|
||||
pid_t childpid;
|
||||
|
||||
fflush(stdout);
|
||||
childpid = fork();
|
||||
|
||||
if (childpid) {
|
||||
waitpid(childpid, &result, 0);
|
||||
if (WIFEXITED(result))
|
||||
return WEXITSTATUS(result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("[RUN]\tExecuting %s\n", name);
|
||||
exit(test());
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
printf("[RUN]\tTesting sync framework\n");
|
||||
|
||||
err += RUN_TEST(test_alloc_timeline);
|
||||
err += RUN_TEST(test_alloc_fence);
|
||||
err += RUN_TEST(test_alloc_fence_negative);
|
||||
|
||||
err += RUN_TEST(test_fence_one_timeline_wait);
|
||||
err += RUN_TEST(test_fence_one_timeline_merge);
|
||||
err += RUN_TEST(test_fence_merge_same_fence);
|
||||
err += RUN_TEST(test_fence_multi_timeline_wait);
|
||||
err += RUN_TEST(test_stress_two_threads_shared_timeline);
|
||||
err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
|
||||
err += RUN_TEST(test_merge_stress_random_merge);
|
||||
|
||||
if (err)
|
||||
printf("[FAIL]\tsync errors: %d\n", err);
|
||||
else
|
||||
printf("[OK]\tsync\n");
|
||||
|
||||
return !!err;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* sync fence wait tests
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 "sync.h"
|
||||
#include "sw_sync.h"
|
||||
#include "synctest.h"
|
||||
|
||||
int test_fence_multi_timeline_wait(void)
|
||||
{
|
||||
int timelineA, timelineB, timelineC;
|
||||
int fenceA, fenceB, fenceC, merged;
|
||||
int valid, active, signaled, ret;
|
||||
|
||||
timelineA = sw_sync_timeline_create();
|
||||
timelineB = sw_sync_timeline_create();
|
||||
timelineC = sw_sync_timeline_create();
|
||||
|
||||
fenceA = sw_sync_fence_create(timelineA, "fenceA", 5);
|
||||
fenceB = sw_sync_fence_create(timelineB, "fenceB", 5);
|
||||
fenceC = sw_sync_fence_create(timelineC, "fenceC", 5);
|
||||
|
||||
merged = sync_merge("mergeFence", fenceB, fenceA);
|
||||
merged = sync_merge("mergeFence", fenceC, merged);
|
||||
|
||||
valid = sw_sync_fence_is_valid(merged);
|
||||
ASSERT(valid, "Failure merging fence from various timelines\n");
|
||||
|
||||
/* Confirm fence isn't signaled */
|
||||
active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
|
||||
ASSERT(active == 3, "Fence signaled too early!\n");
|
||||
|
||||
ret = sync_wait(merged, 0);
|
||||
ASSERT(ret == 0,
|
||||
"Failure waiting on fence until timeout\n");
|
||||
|
||||
ret = sw_sync_timeline_inc(timelineA, 5);
|
||||
active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
|
||||
signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
|
||||
ASSERT(active == 2 && signaled == 1,
|
||||
"Fence did not signal properly!\n");
|
||||
|
||||
ret = sw_sync_timeline_inc(timelineB, 5);
|
||||
active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
|
||||
signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
|
||||
ASSERT(active == 1 && signaled == 2,
|
||||
"Fence did not signal properly!\n");
|
||||
|
||||
ret = sw_sync_timeline_inc(timelineC, 5);
|
||||
active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
|
||||
signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
|
||||
ASSERT(active == 0 && signaled == 3,
|
||||
"Fence did not signal properly!\n");
|
||||
|
||||
/* confirm you can successfully wait */
|
||||
ret = sync_wait(merged, 100);
|
||||
ASSERT(ret > 0, "Failure waiting on signaled fence\n");
|
||||
|
||||
sw_sync_fence_destroy(merged);
|
||||
sw_sync_fence_destroy(fenceC);
|
||||
sw_sync_fence_destroy(fenceB);
|
||||
sw_sync_fence_destroy(fenceA);
|
||||
sw_sync_timeline_destroy(timelineC);
|
||||
sw_sync_timeline_destroy(timelineB);
|
||||
sw_sync_timeline_destroy(timelineA);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* sync tests
|
||||
* Copyright 2015-2016 Collabora Ltd.
|
||||
*
|
||||
* Based on the implementation from the Android Open Source Project,
|
||||
*
|
||||
* Copyright 2012 Google, Inc
|
||||
*
|
||||
* 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 SELFTESTS_SYNCTEST_H
|
||||
#define SELFTESTS_SYNCTEST_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define ASSERT(cond, msg) do { \
|
||||
if (!(cond)) { \
|
||||
printf("[ERROR]\t%s", (msg)); \
|
||||
return 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RUN_TEST(x) run_test((x), #x)
|
||||
|
||||
/* Allocation tests */
|
||||
int test_alloc_timeline(void);
|
||||
int test_alloc_fence(void);
|
||||
int test_alloc_fence_negative(void);
|
||||
|
||||
/* Fence tests with one timeline */
|
||||
int test_fence_one_timeline_wait(void);
|
||||
int test_fence_one_timeline_merge(void);
|
||||
|
||||
/* Fence merge tests */
|
||||
int test_fence_merge_same_fence(void);
|
||||
|
||||
/* Fence wait tests */
|
||||
int test_fence_multi_timeline_wait(void);
|
||||
|
||||
/* Stress test - parallelism */
|
||||
int test_stress_two_threads_shared_timeline(void);
|
||||
|
||||
/* Stress test - consumer */
|
||||
int test_consumer_stress_multi_producer_single_consumer(void);
|
||||
|
||||
/* Stress test - merging */
|
||||
int test_merge_stress_random_merge(void);
|
||||
|
||||
#endif
|
|
@ -17,3 +17,4 @@ skew_consistency
|
|||
threadtest
|
||||
valid-adjtimex
|
||||
adjtick
|
||||
set-tz
|
||||
|
|
Loading…
Reference in New Issue