18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include "tests.h"
38c2ecf20Sopenharmony_ci#include "machine.h"
48c2ecf20Sopenharmony_ci#include "thread.h"
58c2ecf20Sopenharmony_ci#include "debug.h"
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciint test__thread_maps_share(struct test *test __maybe_unused, int subtest __maybe_unused)
88c2ecf20Sopenharmony_ci{
98c2ecf20Sopenharmony_ci	struct machines machines;
108c2ecf20Sopenharmony_ci	struct machine *machine;
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci	/* thread group */
138c2ecf20Sopenharmony_ci	struct thread *leader;
148c2ecf20Sopenharmony_ci	struct thread *t1, *t2, *t3;
158c2ecf20Sopenharmony_ci	struct maps *maps;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	/* other process */
188c2ecf20Sopenharmony_ci	struct thread *other, *other_leader;
198c2ecf20Sopenharmony_ci	struct maps *other_maps;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	/*
228c2ecf20Sopenharmony_ci	 * This test create 2 processes abstractions (struct thread)
238c2ecf20Sopenharmony_ci	 * with several threads and checks they properly share and
248c2ecf20Sopenharmony_ci	 * maintain maps info (struct maps).
258c2ecf20Sopenharmony_ci	 *
268c2ecf20Sopenharmony_ci	 * thread group (pid: 0, tids: 0, 1, 2, 3)
278c2ecf20Sopenharmony_ci	 * other  group (pid: 4, tids: 4, 5)
288c2ecf20Sopenharmony_ci	*/
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	machines__init(&machines);
318c2ecf20Sopenharmony_ci	machine = &machines.host;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	/* create process with 4 threads */
348c2ecf20Sopenharmony_ci	leader = machine__findnew_thread(machine, 0, 0);
358c2ecf20Sopenharmony_ci	t1     = machine__findnew_thread(machine, 0, 1);
368c2ecf20Sopenharmony_ci	t2     = machine__findnew_thread(machine, 0, 2);
378c2ecf20Sopenharmony_ci	t3     = machine__findnew_thread(machine, 0, 3);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	/* and create 1 separated process, without thread leader */
408c2ecf20Sopenharmony_ci	other  = machine__findnew_thread(machine, 4, 5);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to create threads",
438c2ecf20Sopenharmony_ci			leader && t1 && t2 && t3 && other);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	maps = leader->maps;
468c2ecf20Sopenharmony_ci	TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&maps->refcnt), 4);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	/* test the maps pointer is shared */
498c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("maps don't match", maps == t1->maps);
508c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("maps don't match", maps == t2->maps);
518c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("maps don't match", maps == t3->maps);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	/*
548c2ecf20Sopenharmony_ci	 * Verify the other leader was created by previous call.
558c2ecf20Sopenharmony_ci	 * It should have shared maps with no change in
568c2ecf20Sopenharmony_ci	 * refcnt.
578c2ecf20Sopenharmony_ci	 */
588c2ecf20Sopenharmony_ci	other_leader = machine__find_thread(machine, 4, 4);
598c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to find other leader", other_leader);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	/*
628c2ecf20Sopenharmony_ci	 * Ok, now that all the rbtree related operations were done,
638c2ecf20Sopenharmony_ci	 * lets remove all of them from there so that we can do the
648c2ecf20Sopenharmony_ci	 * refcounting tests.
658c2ecf20Sopenharmony_ci	 */
668c2ecf20Sopenharmony_ci	machine__remove_thread(machine, leader);
678c2ecf20Sopenharmony_ci	machine__remove_thread(machine, t1);
688c2ecf20Sopenharmony_ci	machine__remove_thread(machine, t2);
698c2ecf20Sopenharmony_ci	machine__remove_thread(machine, t3);
708c2ecf20Sopenharmony_ci	machine__remove_thread(machine, other);
718c2ecf20Sopenharmony_ci	machine__remove_thread(machine, other_leader);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	other_maps = other->maps;
748c2ecf20Sopenharmony_ci	TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&other_maps->refcnt), 2);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("maps don't match", other_maps == other_leader->maps);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	/* release thread group */
798c2ecf20Sopenharmony_ci	thread__put(leader);
808c2ecf20Sopenharmony_ci	TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&maps->refcnt), 3);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	thread__put(t1);
838c2ecf20Sopenharmony_ci	TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&maps->refcnt), 2);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	thread__put(t2);
868c2ecf20Sopenharmony_ci	TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&maps->refcnt), 1);
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	thread__put(t3);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	/* release other group  */
918c2ecf20Sopenharmony_ci	thread__put(other_leader);
928c2ecf20Sopenharmony_ci	TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&other_maps->refcnt), 1);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	thread__put(other);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	machines__exit(&machines);
978c2ecf20Sopenharmony_ci	return 0;
988c2ecf20Sopenharmony_ci}
99